home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / libtool / libltdl / ltdl.c < prev    next >
C/C++ Source or Header  |  2006-04-25  |  99KB  |  4,522 lines

  1. /* ltdl.c -- system independent dlopen wrapper
  2.    Copyright (C) 1998, 1999, 2000, 2004, 2005  Free Software Foundation, Inc.
  3.    Originally by Thomas Tanner <tanner@ffii.org>
  4.    This file is part of GNU Libtool.
  5.  
  6. This library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Lesser General Public
  8. License as published by the Free Software Foundation; either
  9. version 2 of the License, or (at your option) any later version.
  10.  
  11. As a special exception to the GNU Lesser General Public License,
  12. if you distribute this file as part of a program or library that
  13. is built using GNU libtool, you may include it under the same
  14. distribution terms that you use for the rest of that program.
  15.  
  16. This library is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19. Lesser General Public License for more details.
  20.  
  21. You should have received a copy of the GNU Lesser General Public
  22. License along with this library; if not, write to the Free Software
  23. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  24. 02110-1301  USA
  25.  
  26. */
  27.  
  28. #if HAVE_CONFIG_H
  29. #  include <config.h>
  30. #endif
  31.  
  32. #if HAVE_UNISTD_H
  33. #  include <unistd.h>
  34. #endif
  35.  
  36. #if HAVE_STDIO_H
  37. #  include <stdio.h>
  38. #endif
  39.  
  40. /* Include the header defining malloc.  On K&R C compilers,
  41.    that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
  42. #if HAVE_STDLIB_H
  43. #  include <stdlib.h>
  44. #else
  45. #  if HAVE_MALLOC_H
  46. #    include <malloc.h>
  47. #  endif
  48. #endif
  49.  
  50. #if HAVE_STRING_H
  51. #  include <string.h>
  52. #else
  53. #  if HAVE_STRINGS_H
  54. #    include <strings.h>
  55. #  endif
  56. #endif
  57.  
  58. #if HAVE_CTYPE_H
  59. #  include <ctype.h>
  60. #endif
  61.  
  62. #if HAVE_MEMORY_H
  63. #  include <memory.h>
  64. #endif
  65.  
  66. #if HAVE_ERRNO_H
  67. #  include <errno.h>
  68. #endif
  69.  
  70.  
  71. #ifndef __WINDOWS__
  72. #  ifdef __WIN32__
  73. #    define __WINDOWS__
  74. #  endif
  75. #endif
  76.  
  77.  
  78. #undef LT_USE_POSIX_DIRENT
  79. #ifdef HAVE_CLOSEDIR
  80. #  ifdef HAVE_OPENDIR
  81. #    ifdef HAVE_READDIR
  82. #      ifdef HAVE_DIRENT_H
  83. #        define LT_USE_POSIX_DIRENT
  84. #      endif /* HAVE_DIRENT_H */
  85. #    endif /* HAVE_READDIR */
  86. #  endif /* HAVE_OPENDIR */
  87. #endif /* HAVE_CLOSEDIR */
  88.  
  89.  
  90. #undef LT_USE_WINDOWS_DIRENT_EMULATION
  91. #ifndef LT_USE_POSIX_DIRENT
  92. #  ifdef __WINDOWS__
  93. #    define LT_USE_WINDOWS_DIRENT_EMULATION
  94. #  endif /* __WINDOWS__ */
  95. #endif /* LT_USE_POSIX_DIRENT */
  96.  
  97.  
  98. #ifdef LT_USE_POSIX_DIRENT
  99. #  include <dirent.h>
  100. #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
  101. #else
  102. #  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  103. #    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
  104. #  else
  105. #    define dirent direct
  106. #    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
  107. #    if HAVE_SYS_NDIR_H
  108. #      include <sys/ndir.h>
  109. #    endif
  110. #    if HAVE_SYS_DIR_H
  111. #      include <sys/dir.h>
  112. #    endif
  113. #    if HAVE_NDIR_H
  114. #      include <ndir.h>
  115. #    endif
  116. #  endif
  117. #endif
  118.  
  119. #if HAVE_ARGZ_H
  120. #  include <argz.h>
  121. #endif
  122.  
  123. #if HAVE_ASSERT_H
  124. #  include <assert.h>
  125. #else
  126. #  define assert(arg)    ((void) 0)
  127. #endif
  128.  
  129. #include "ltdl.h"
  130.  
  131. #if WITH_DMALLOC
  132. #  include <dmalloc.h>
  133. #endif
  134.  
  135.  
  136.  
  137.  
  138. /* --- WINDOWS SUPPORT --- */
  139.  
  140.  
  141. #ifdef DLL_EXPORT
  142. #  define LT_GLOBAL_DATA    __declspec(dllexport)
  143. #else
  144. #  define LT_GLOBAL_DATA
  145. #endif
  146.  
  147. /* fopen() mode flags for reading a text file */
  148. #undef    LT_READTEXT_MODE
  149. #ifdef __WINDOWS__
  150. #  define LT_READTEXT_MODE "rt"
  151. #else
  152. #  define LT_READTEXT_MODE "r"
  153. #endif
  154.  
  155. #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  156.  
  157. #include <windows.h>
  158.  
  159. #define dirent lt_dirent
  160. #define DIR lt_DIR
  161.  
  162. struct dirent
  163. {
  164.   char d_name[2048];
  165.   int  d_namlen;
  166. };
  167.  
  168. typedef struct _DIR
  169. {
  170.   HANDLE hSearch;
  171.   WIN32_FIND_DATA Win32FindData;
  172.   BOOL firsttime;
  173.   struct dirent file_info;
  174. } DIR;
  175.  
  176. #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
  177.  
  178.  
  179. /* --- MANIFEST CONSTANTS --- */
  180.  
  181.  
  182. /* Standard libltdl search path environment variable name  */
  183. #undef  LTDL_SEARCHPATH_VAR
  184. #define LTDL_SEARCHPATH_VAR    "LTDL_LIBRARY_PATH"
  185.  
  186. /* Standard libtool archive file extension.  */
  187. #undef  LTDL_ARCHIVE_EXT
  188. #define LTDL_ARCHIVE_EXT    ".la"
  189.  
  190. /* max. filename length */
  191. #ifndef LT_FILENAME_MAX
  192. #  define LT_FILENAME_MAX    1024
  193. #endif
  194.  
  195. /* This is the maximum symbol size that won't require malloc/free */
  196. #undef    LT_SYMBOL_LENGTH
  197. #define LT_SYMBOL_LENGTH    128
  198.  
  199. /* This accounts for the _LTX_ separator */
  200. #undef    LT_SYMBOL_OVERHEAD
  201. #define LT_SYMBOL_OVERHEAD    5
  202.  
  203.  
  204.  
  205.  
  206. /* --- MEMORY HANDLING --- */
  207.  
  208.  
  209. /* These are the functions used internally.  In addition to making
  210.    use of the associated function pointers above, they also perform
  211.    error handling.  */
  212. static char   *lt_estrdup    LT_PARAMS((const char *str));
  213. static lt_ptr lt_emalloc    LT_PARAMS((size_t size));
  214. static lt_ptr lt_erealloc    LT_PARAMS((lt_ptr addr, size_t size));
  215.  
  216. /* static lt_ptr rpl_realloc    LT_PARAMS((lt_ptr ptr, size_t size)); */
  217. #define rpl_realloc realloc
  218.  
  219. /* These are the pointers that can be changed by the caller:  */
  220. LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
  221.              = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
  222. LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)    LT_PARAMS((lt_ptr ptr, size_t size))
  223.              = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
  224. LT_GLOBAL_DATA void   (*lt_dlfree)    LT_PARAMS((lt_ptr ptr))
  225.              = (void (*) LT_PARAMS((lt_ptr))) free;
  226.  
  227. /* The following macros reduce the amount of typing needed to cast
  228.    assigned memory.  */
  229. #if WITH_DMALLOC
  230.  
  231. #define LT_DLMALLOC(tp, n)    ((tp *) xmalloc ((n) * sizeof(tp)))
  232. #define LT_DLREALLOC(tp, p, n)    ((tp *) xrealloc ((p), (n) * sizeof(tp)))
  233. #define LT_DLFREE(p)                        \
  234.     LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
  235.  
  236. #define LT_EMALLOC(tp, n)    ((tp *) xmalloc ((n) * sizeof(tp)))
  237. #define LT_EREALLOC(tp, p, n)    ((tp *) xrealloc ((p), (n) * sizeof(tp)))
  238.  
  239. #else
  240.  
  241. #define LT_DLMALLOC(tp, n)    ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
  242. #define LT_DLREALLOC(tp, p, n)    ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
  243. #define LT_DLFREE(p)                        \
  244.     LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
  245.  
  246. #define LT_EMALLOC(tp, n)    ((tp *) lt_emalloc ((n) * sizeof(tp)))
  247. #define LT_EREALLOC(tp, p, n)    ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
  248.  
  249. #endif
  250.  
  251. #define LT_DLMEM_REASSIGN(p, q)            LT_STMT_START {    \
  252.     if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }    \
  253.                         } LT_STMT_END
  254.  
  255.  
  256. /* --- REPLACEMENT FUNCTIONS --- */
  257.  
  258.  
  259. #undef strdup
  260. #define strdup rpl_strdup
  261.  
  262. static char *strdup LT_PARAMS((const char *str));
  263.  
  264. static char *
  265. strdup(str)
  266.      const char *str;
  267. {
  268.   char *tmp = 0;
  269.  
  270.   if (str)
  271.     {
  272.       tmp = LT_DLMALLOC (char, 1+ strlen (str));
  273.       if (tmp)
  274.     {
  275.       strcpy(tmp, str);
  276.     }
  277.     }
  278.  
  279.   return tmp;
  280. }
  281.  
  282.  
  283. #if ! HAVE_STRCMP
  284.  
  285. #undef strcmp
  286. #define strcmp rpl_strcmp
  287.  
  288. static int strcmp LT_PARAMS((const char *str1, const char *str2));
  289.  
  290. static int
  291. strcmp (str1, str2)
  292.      const char *str1;
  293.      const char *str2;
  294. {
  295.   if (str1 == str2)
  296.     return 0;
  297.   if (str1 == 0)
  298.     return -1;
  299.   if (str2 == 0)
  300.     return 1;
  301.  
  302.   for (;*str1 && *str2; ++str1, ++str2)
  303.     {
  304.       if (*str1 != *str2)
  305.     break;
  306.     }
  307.  
  308.   return (int)(*str1 - *str2);
  309. }
  310. #endif
  311.  
  312.  
  313. #if ! HAVE_STRCHR
  314.  
  315. #  if HAVE_INDEX
  316. #    define strchr index
  317. #  else
  318. #    define strchr rpl_strchr
  319.  
  320. static const char *strchr LT_PARAMS((const char *str, int ch));
  321.  
  322. static const char*
  323. strchr(str, ch)
  324.      const char *str;
  325.      int ch;
  326. {
  327.   const char *p;
  328.  
  329.   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
  330.     /*NOWORK*/;
  331.  
  332.   return (*p == (char)ch) ? p : 0;
  333. }
  334.  
  335. #  endif
  336. #endif /* !HAVE_STRCHR */
  337.  
  338.  
  339. #if ! HAVE_STRRCHR
  340.  
  341. #  if HAVE_RINDEX
  342. #    define strrchr rindex
  343. #  else
  344. #    define strrchr rpl_strrchr
  345.  
  346. static const char *strrchr LT_PARAMS((const char *str, int ch));
  347.  
  348. static const char*
  349. strrchr(str, ch)
  350.      const char *str;
  351.      int ch;
  352. {
  353.   const char *p, *q = 0;
  354.  
  355.   for (p = str; *p != LT_EOS_CHAR; ++p)
  356.     {
  357.       if (*p == (char) ch)
  358.     {
  359.       q = p;
  360.     }
  361.     }
  362.  
  363.   return q;
  364. }
  365.  
  366. # endif
  367. #endif
  368.  
  369. /* NOTE:  Neither bcopy nor the memcpy implementation below can
  370.           reliably handle copying in overlapping areas of memory.  Use
  371.           memmove (for which there is a fallback implmentation below)
  372.       if you need that behaviour.  */
  373. #if ! HAVE_MEMCPY
  374.  
  375. #  if HAVE_BCOPY
  376. #    define memcpy(dest, src, size)    bcopy (src, dest, size)
  377. #  else
  378. #    define memcpy rpl_memcpy
  379.  
  380. static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
  381.  
  382. static lt_ptr
  383. memcpy (dest, src, size)
  384.      lt_ptr dest;
  385.      const lt_ptr src;
  386.      size_t size;
  387. {
  388.   const char *    s = src;
  389.   char *    d = dest;
  390.   size_t    i = 0;
  391.  
  392.   for (i = 0; i < size; ++i)
  393.     {
  394.       d[i] = s[i];
  395.     }
  396.  
  397.   return dest;
  398. }
  399.  
  400. #  endif /* !HAVE_BCOPY */
  401. #endif   /* !HAVE_MEMCPY */
  402.  
  403. #if ! HAVE_MEMMOVE
  404. #  define memmove rpl_memmove
  405.  
  406. static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
  407.  
  408. static lt_ptr
  409. memmove (dest, src, size)
  410.      lt_ptr dest;
  411.      const lt_ptr src;
  412.      size_t size;
  413. {
  414.   const char *    s = src;
  415.   char *    d = dest;
  416.   size_t    i;
  417.  
  418.   if (d < s)
  419.     for (i = 0; i < size; ++i)
  420.       {
  421.     d[i] = s[i];
  422.       }
  423.   else if (d > s && size > 0)
  424.     for (i = size -1; ; --i)
  425.       {
  426.     d[i] = s[i];
  427.     if (i == 0)
  428.       break;
  429.       }
  430.  
  431.   return dest;
  432. }
  433.  
  434. #endif /* !HAVE_MEMMOVE */
  435.  
  436. #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  437.  
  438. static void closedir LT_PARAMS((DIR *entry));
  439.  
  440. static void
  441. closedir(entry)
  442.   DIR *entry;
  443. {
  444.   assert(entry != (DIR *) NULL);
  445.   FindClose(entry->hSearch);
  446.   lt_dlfree((lt_ptr)entry);
  447. }
  448.  
  449.  
  450. static DIR * opendir LT_PARAMS((const char *path));
  451.  
  452. static DIR*
  453. opendir (path)
  454.   const char *path;
  455. {
  456.   char file_specification[LT_FILENAME_MAX];
  457.   DIR *entry;
  458.  
  459.   assert(path != (char *) NULL);
  460.   /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
  461.   (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
  462.   file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
  463.   (void) strcat(file_specification,"\\");
  464.   entry = LT_DLMALLOC (DIR,sizeof(DIR));
  465.   if (entry != (DIR *) 0)
  466.     {
  467.       entry->firsttime = TRUE;
  468.       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
  469.     }
  470.   if (entry->hSearch == INVALID_HANDLE_VALUE)
  471.     {
  472.       (void) strcat(file_specification,"\\*.*");
  473.       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
  474.       if (entry->hSearch == INVALID_HANDLE_VALUE)
  475.         {
  476.           LT_DLFREE (entry);
  477.           return (DIR *) 0;
  478.         }
  479.     }
  480.   return(entry);
  481. }
  482.  
  483.  
  484. static struct dirent *readdir LT_PARAMS((DIR *entry));
  485.  
  486. static struct dirent *readdir(entry)
  487.   DIR *entry;
  488. {
  489.   int
  490.     status;
  491.  
  492.   if (entry == (DIR *) 0)
  493.     return((struct dirent *) 0);
  494.   if (!entry->firsttime)
  495.     {
  496.       status = FindNextFile(entry->hSearch,&entry->Win32FindData);
  497.       if (status == 0)
  498.         return((struct dirent *) 0);
  499.     }
  500.   entry->firsttime = FALSE;
  501.   (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
  502.     LT_FILENAME_MAX-1);
  503.   entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
  504.   entry->file_info.d_namlen = strlen(entry->file_info.d_name);
  505.   return(&entry->file_info);
  506. }
  507.  
  508. #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
  509.  
  510. /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
  511.     ``realloc is not entirely portable''
  512.    In any case we want to use the allocator supplied by the user without
  513.    burdening them with an lt_dlrealloc function pointer to maintain.
  514.    Instead implement our own version (with known boundary conditions)
  515.    using lt_dlmalloc and lt_dlfree. */
  516.  
  517. /* #undef realloc
  518.    #define realloc rpl_realloc
  519. */
  520. #if 0
  521.   /* You can't (re)define realloc unless you also (re)define malloc.
  522.      Right now, this code uses the size of the *destination* to decide
  523.      how much to copy.  That's not right, but you can't know the size
  524.      of the source unless you know enough about, or wrote malloc.  So
  525.      this code is disabled... */
  526.  
  527. static lt_ptr
  528. realloc (ptr, size)
  529.      lt_ptr ptr;
  530.      size_t size;
  531. {
  532.   if (size == 0)
  533.     {
  534.       /* For zero or less bytes, free the original memory */
  535.       if (ptr != 0)
  536.     {
  537.       lt_dlfree (ptr);
  538.     }
  539.  
  540.       return (lt_ptr) 0;
  541.     }
  542.   else if (ptr == 0)
  543.     {
  544.       /* Allow reallocation of a NULL pointer.  */
  545.       return lt_dlmalloc (size);
  546.     }
  547.   else
  548.     {
  549.       /* Allocate a new block, copy and free the old block.  */
  550.       lt_ptr mem = lt_dlmalloc (size);
  551.  
  552.       if (mem)
  553.     {
  554.       memcpy (mem, ptr, size);
  555.       lt_dlfree (ptr);
  556.     }
  557.  
  558.       /* Note that the contents of PTR are not damaged if there is
  559.      insufficient memory to realloc.  */
  560.       return mem;
  561.     }
  562. }
  563. #endif
  564.  
  565.  
  566. #if ! HAVE_ARGZ_APPEND
  567. #  define argz_append rpl_argz_append
  568.  
  569. static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
  570.                     const char *buf, size_t buf_len));
  571.  
  572. static error_t
  573. argz_append (pargz, pargz_len, buf, buf_len)
  574.      char **pargz;
  575.      size_t *pargz_len;
  576.      const char *buf;
  577.      size_t buf_len;
  578. {
  579.   size_t argz_len;
  580.   char  *argz;
  581.  
  582.   assert (pargz);
  583.   assert (pargz_len);
  584.   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
  585.  
  586.   /* If nothing needs to be appended, no more work is required.  */
  587.   if (buf_len == 0)
  588.     return 0;
  589.  
  590.   /* Ensure there is enough room to append BUF_LEN.  */
  591.   argz_len = *pargz_len + buf_len;
  592.   argz = LT_DLREALLOC (char, *pargz, argz_len);
  593.   if (!argz)
  594.     return ENOMEM;
  595.  
  596.   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
  597.   memcpy (argz + *pargz_len, buf, buf_len);
  598.  
  599.   /* Assign new values.  */
  600.   *pargz = argz;
  601.   *pargz_len = argz_len;
  602.  
  603.   return 0;
  604. }
  605. #endif /* !HAVE_ARGZ_APPEND */
  606.  
  607.  
  608. #if ! HAVE_ARGZ_CREATE_SEP
  609. #  define argz_create_sep rpl_argz_create_sep
  610.  
  611. static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
  612.                         char **pargz, size_t *pargz_len));
  613.  
  614. static error_t
  615. argz_create_sep (str, delim, pargz, pargz_len)
  616.      const char *str;
  617.      int delim;
  618.      char **pargz;
  619.      size_t *pargz_len;
  620. {
  621.   size_t argz_len;
  622.   char *argz = 0;
  623.  
  624.   assert (str);
  625.   assert (pargz);
  626.   assert (pargz_len);
  627.  
  628.   /* Make a copy of STR, but replacing each occurrence of
  629.      DELIM with '\0'.  */
  630.   argz_len = 1+ LT_STRLEN (str);
  631.   if (argz_len)
  632.     {
  633.       const char *p;
  634.       char *q;
  635.  
  636.       argz = LT_DLMALLOC (char, argz_len);
  637.       if (!argz)
  638.     return ENOMEM;
  639.  
  640.       for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
  641.     {
  642.       if (*p == delim)
  643.         {
  644.           /* Ignore leading delimiters, and fold consecutive
  645.          delimiters in STR into a single '\0' in ARGZ.  */
  646.           if ((q > argz) && (q[-1] != LT_EOS_CHAR))
  647.         *q++ = LT_EOS_CHAR;
  648.           else
  649.         --argz_len;
  650.         }
  651.       else
  652.         *q++ = *p;
  653.     }
  654.       /* Copy terminating LT_EOS_CHAR.  */
  655.       *q = *p;
  656.     }
  657.  
  658.   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
  659.   if (!argz_len)
  660.     LT_DLFREE (argz);
  661.  
  662.   /* Assign new values.  */
  663.   *pargz = argz;
  664.   *pargz_len = argz_len;
  665.  
  666.   return 0;
  667. }
  668. #endif /* !HAVE_ARGZ_CREATE_SEP */
  669.  
  670.  
  671. #if ! HAVE_ARGZ_INSERT
  672. #  define argz_insert rpl_argz_insert
  673.  
  674. static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
  675.                     char *before, const char *entry));
  676.  
  677. static error_t
  678. argz_insert (pargz, pargz_len, before, entry)
  679.      char **pargz;
  680.      size_t *pargz_len;
  681.      char *before;
  682.      const char *entry;
  683. {
  684.   assert (pargz);
  685.   assert (pargz_len);
  686.   assert (entry && *entry);
  687.  
  688.   /* No BEFORE address indicates ENTRY should be inserted after the
  689.      current last element.  */
  690.   if (!before)
  691.     return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
  692.  
  693.   /* This probably indicates a programmer error, but to preserve
  694.      semantics, scan back to the start of an entry if BEFORE points
  695.      into the middle of it.  */
  696.   while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
  697.     --before;
  698.  
  699.   {
  700.     size_t entry_len    = 1+ LT_STRLEN (entry);
  701.     size_t argz_len    = *pargz_len + entry_len;
  702.     size_t offset    = before - *pargz;
  703.     char   *argz    = LT_DLREALLOC (char, *pargz, argz_len);
  704.  
  705.     if (!argz)
  706.       return ENOMEM;
  707.  
  708.     /* Make BEFORE point to the equivalent offset in ARGZ that it
  709.        used to have in *PARGZ incase realloc() moved the block.  */
  710.     before = argz + offset;
  711.  
  712.     /* Move the ARGZ entries starting at BEFORE up into the new
  713.        space at the end -- making room to copy ENTRY into the
  714.        resulting gap.  */
  715.     memmove (before + entry_len, before, *pargz_len - offset);
  716.     memcpy  (before, entry, entry_len);
  717.  
  718.     /* Assign new values.  */
  719.     *pargz = argz;
  720.     *pargz_len = argz_len;
  721.   }
  722.  
  723.   return 0;
  724. }
  725. #endif /* !HAVE_ARGZ_INSERT */
  726.  
  727.  
  728. #if ! HAVE_ARGZ_NEXT
  729. #  define argz_next rpl_argz_next
  730.  
  731. static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
  732.                     const char *entry));
  733.  
  734. static char *
  735. argz_next (argz, argz_len, entry)
  736.      char *argz;
  737.      size_t argz_len;
  738.      const char *entry;
  739. {
  740.   assert ((argz && argz_len) || (!argz && !argz_len));
  741.  
  742.   if (entry)
  743.     {
  744.       /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
  745.      within the ARGZ vector.  */
  746.       assert ((!argz && !argz_len)
  747.           || ((argz <= entry) && (entry < (argz + argz_len))));
  748.  
  749.       /* Move to the char immediately after the terminating
  750.      '\0' of ENTRY.  */
  751.       entry = 1+ strchr (entry, LT_EOS_CHAR);
  752.  
  753.       /* Return either the new ENTRY, or else NULL if ARGZ is
  754.      exhausted.  */
  755.       return (entry >= argz + argz_len) ? 0 : (char *) entry;
  756.     }
  757.   else
  758.     {
  759.       /* This should probably be flagged as a programmer error,
  760.      since starting an argz_next loop with the iterator set
  761.      to ARGZ is safer.  To preserve semantics, handle the NULL
  762.      case by returning the start of ARGZ (if any).  */
  763.       if (argz_len > 0)
  764.     return argz;
  765.       else
  766.     return 0;
  767.     }
  768. }
  769. #endif /* !HAVE_ARGZ_NEXT */
  770.  
  771.  
  772.  
  773. #if ! HAVE_ARGZ_STRINGIFY
  774. #  define argz_stringify rpl_argz_stringify
  775.  
  776. static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
  777.                        int sep));
  778.  
  779. static void
  780. argz_stringify (argz, argz_len, sep)
  781.      char *argz;
  782.      size_t argz_len;
  783.      int sep;
  784. {
  785.   assert ((argz && argz_len) || (!argz && !argz_len));
  786.  
  787.   if (sep)
  788.     {
  789.       --argz_len;        /* don't stringify the terminating EOS */
  790.       while (--argz_len > 0)
  791.     {
  792.       if (argz[argz_len] == LT_EOS_CHAR)
  793.         argz[argz_len] = sep;
  794.     }
  795.     }
  796. }
  797. #endif /* !HAVE_ARGZ_STRINGIFY */
  798.  
  799.  
  800.  
  801.  
  802. /* --- TYPE DEFINITIONS -- */
  803.  
  804.  
  805. /* This type is used for the array of caller data sets in each handler. */
  806. typedef struct {
  807.   lt_dlcaller_id    key;
  808.   lt_ptr        data;
  809. } lt_caller_data;
  810.  
  811.  
  812.  
  813.  
  814. /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
  815.  
  816.  
  817. /* Extract the diagnostic strings from the error table macro in the same
  818.    order as the enumerated indices in ltdl.h. */
  819.  
  820. static const char *lt_dlerror_strings[] =
  821.   {
  822. #define LT_ERROR(name, diagnostic)    (diagnostic),
  823.     lt_dlerror_table
  824. #undef LT_ERROR
  825.  
  826.     0
  827.   };
  828.  
  829. /* This structure is used for the list of registered loaders. */
  830. struct lt_dlloader {
  831.   struct lt_dlloader   *next;
  832.   const char           *loader_name;    /* identifying name for each loader */
  833.   const char           *sym_prefix;    /* prefix for symbols */
  834.   lt_module_open       *module_open;
  835.   lt_module_close      *module_close;
  836.   lt_find_sym           *find_sym;
  837.   lt_dlloader_exit     *dlloader_exit;
  838.   lt_user_data        dlloader_data;
  839. };
  840.  
  841. struct lt_dlhandle_struct {
  842.   struct lt_dlhandle_struct   *next;
  843.   lt_dlloader           *loader;        /* dlopening interface */
  844.   lt_dlinfo        info;
  845.   int            depcount;    /* number of dependencies */
  846.   lt_dlhandle           *deplibs;    /* dependencies */
  847.   lt_module        module;        /* system module handle */
  848.   lt_ptr        system;        /* system specific data */
  849.   lt_caller_data       *caller_data;    /* per caller associated data */
  850.   int            flags;        /* various boolean stats */
  851. };
  852.  
  853. /* Various boolean flags can be stored in the flags field of an
  854.    lt_dlhandle_struct... */
  855. #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
  856. #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
  857.  
  858. #define LT_DLRESIDENT_FLAG        (0x01 << 0)
  859. /* ...add more flags here... */
  860.  
  861. #define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
  862.  
  863.  
  864. #define LT_DLSTRERROR(name)    lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
  865.  
  866. static    const char    objdir[]        = LTDL_OBJDIR;
  867. static    const char    archive_ext[]        = LTDL_ARCHIVE_EXT;
  868. #ifdef    LTDL_SHLIB_EXT
  869. static    const char    shlib_ext[]        = LTDL_SHLIB_EXT;
  870. #endif
  871. #ifdef    LTDL_SYSSEARCHPATH
  872. static    const char    sys_search_path[]    = LTDL_SYSSEARCHPATH;
  873. #endif
  874.  
  875.  
  876.  
  877.  
  878. /* --- MUTEX LOCKING --- */
  879.  
  880.  
  881. /* Macros to make it easier to run the lock functions only if they have
  882.    been registered.  The reason for the complicated lock macro is to
  883.    ensure that the stored error message from the last error is not
  884.    accidentally erased if the current function doesn't generate an
  885.    error of its own.  */
  886. #define LT_DLMUTEX_LOCK()            LT_STMT_START {    \
  887.     if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
  888.                         } LT_STMT_END
  889. #define LT_DLMUTEX_UNLOCK()            LT_STMT_START { \
  890.     if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
  891.                         } LT_STMT_END
  892. #define LT_DLMUTEX_SETERROR(errormsg)        LT_STMT_START {    \
  893.     if (lt_dlmutex_seterror_func)                \
  894.         (*lt_dlmutex_seterror_func) (errormsg);        \
  895.     else     lt_dllast_error = (errormsg);    } LT_STMT_END
  896. #define LT_DLMUTEX_GETERROR(errormsg)        LT_STMT_START {    \
  897.     if (lt_dlmutex_seterror_func)                \
  898.         (errormsg) = (*lt_dlmutex_geterror_func) ();    \
  899.     else    (errormsg) = lt_dllast_error;    } LT_STMT_END
  900.  
  901. /* The mutex functions stored here are global, and are necessarily the
  902.    same for all threads that wish to share access to libltdl.  */
  903. static    lt_dlmutex_lock        *lt_dlmutex_lock_func     = 0;
  904. static    lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
  905. static    lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
  906. static    lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
  907. static    const char        *lt_dllast_error          = 0;
  908.  
  909.  
  910. /* Either set or reset the mutex functions.  Either all the arguments must
  911.    be valid functions, or else all can be NULL to turn off locking entirely.
  912.    The registered functions should be manipulating a static global lock
  913.    from the lock() and unlock() callbacks, which needs to be reentrant.  */
  914. int
  915. lt_dlmutex_register (lock, unlock, seterror, geterror)
  916.      lt_dlmutex_lock *lock;
  917.      lt_dlmutex_unlock *unlock;
  918.      lt_dlmutex_seterror *seterror;
  919.      lt_dlmutex_geterror *geterror;
  920. {
  921.   lt_dlmutex_unlock *old_unlock = unlock;
  922.   int             errors    = 0;
  923.  
  924.   /* Lock using the old lock() callback, if any.  */
  925.   LT_DLMUTEX_LOCK ();
  926.  
  927.   if ((lock && unlock && seterror && geterror)
  928.       || !(lock || unlock || seterror || geterror))
  929.     {
  930.       lt_dlmutex_lock_func     = lock;
  931.       lt_dlmutex_unlock_func   = unlock;
  932.       lt_dlmutex_geterror_func = geterror;
  933.     }
  934.   else
  935.     {
  936.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
  937.       ++errors;
  938.     }
  939.  
  940.   /* Use the old unlock() callback we saved earlier, if any.  Otherwise
  941.      record any errors using internal storage.  */
  942.   if (old_unlock)
  943.     (*old_unlock) ();
  944.  
  945.   /* Return the number of errors encountered during the execution of
  946.      this function.  */
  947.   return errors;
  948. }
  949.  
  950.  
  951.  
  952.  
  953. /* --- ERROR HANDLING --- */
  954.  
  955.  
  956. static    const char    **user_error_strings    = 0;
  957. static    int        errorcount        = LT_ERROR_MAX;
  958.  
  959. int
  960. lt_dladderror (diagnostic)
  961.      const char *diagnostic;
  962. {
  963.   int        errindex = 0;
  964.   int        result     = -1;
  965.   const char  **temp     = (const char **) 0;
  966.  
  967.   assert (diagnostic);
  968.  
  969.   LT_DLMUTEX_LOCK ();
  970.  
  971.   errindex = errorcount - LT_ERROR_MAX;
  972.   temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
  973.   if (temp)
  974.     {
  975.       user_error_strings        = temp;
  976.       user_error_strings[errindex]    = diagnostic;
  977.       result                = errorcount++;
  978.     }
  979.  
  980.   LT_DLMUTEX_UNLOCK ();
  981.  
  982.   return result;
  983. }
  984.  
  985. int
  986. lt_dlseterror (errindex)
  987.      int errindex;
  988. {
  989.   int        errors     = 0;
  990.  
  991.   LT_DLMUTEX_LOCK ();
  992.  
  993.   if (errindex >= errorcount || errindex < 0)
  994.     {
  995.       /* Ack!  Error setting the error message! */
  996.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
  997.       ++errors;
  998.     }
  999.   else if (errindex < LT_ERROR_MAX)
  1000.     {
  1001.       /* No error setting the error message! */
  1002.       LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
  1003.     }
  1004.   else
  1005.     {
  1006.       /* No error setting the error message! */
  1007.       LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
  1008.     }
  1009.  
  1010.   LT_DLMUTEX_UNLOCK ();
  1011.  
  1012.   return errors;
  1013. }
  1014.  
  1015. static lt_ptr
  1016. lt_emalloc (size)
  1017.      size_t size;
  1018. {
  1019.   lt_ptr mem = lt_dlmalloc (size);
  1020.   if (size && !mem)
  1021.     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  1022.   return mem;
  1023. }
  1024.  
  1025. static lt_ptr
  1026. lt_erealloc (addr, size)
  1027.      lt_ptr addr;
  1028.      size_t size;
  1029. {
  1030.   lt_ptr mem = lt_dlrealloc (addr, size);
  1031.   if (size && !mem)
  1032.     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  1033.   return mem;
  1034. }
  1035.  
  1036. static char *
  1037. lt_estrdup (str)
  1038.      const char *str;
  1039. {
  1040.   char *copy = strdup (str);
  1041.   if (LT_STRLEN (str) && !copy)
  1042.     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  1043.   return copy;
  1044. }
  1045.  
  1046.  
  1047.  
  1048.  
  1049. /* --- DLOPEN() INTERFACE LOADER --- */
  1050.  
  1051.  
  1052. #if HAVE_LIBDL
  1053.  
  1054. /* dynamic linking with dlopen/dlsym */
  1055.  
  1056. #if HAVE_DLFCN_H
  1057. #  include <dlfcn.h>
  1058. #endif
  1059.  
  1060. #if HAVE_SYS_DL_H
  1061. #  include <sys/dl.h>
  1062. #endif
  1063.  
  1064. #ifdef RTLD_GLOBAL
  1065. #  define LT_GLOBAL        RTLD_GLOBAL
  1066. #else
  1067. #  ifdef DL_GLOBAL
  1068. #    define LT_GLOBAL        DL_GLOBAL
  1069. #  endif
  1070. #endif /* !RTLD_GLOBAL */
  1071. #ifndef LT_GLOBAL
  1072. #  define LT_GLOBAL        0
  1073. #endif /* !LT_GLOBAL */
  1074.  
  1075. /* We may have to define LT_LAZY_OR_NOW in the command line if we
  1076.    find out it does not work in some platform. */
  1077. #ifndef LT_LAZY_OR_NOW
  1078. #  ifdef RTLD_LAZY
  1079. #    define LT_LAZY_OR_NOW    RTLD_LAZY
  1080. #  else
  1081. #    ifdef DL_LAZY
  1082. #      define LT_LAZY_OR_NOW    DL_LAZY
  1083. #    endif
  1084. #  endif /* !RTLD_LAZY */
  1085. #endif
  1086. #ifndef LT_LAZY_OR_NOW
  1087. #  ifdef RTLD_NOW
  1088. #    define LT_LAZY_OR_NOW    RTLD_NOW
  1089. #  else
  1090. #    ifdef DL_NOW
  1091. #      define LT_LAZY_OR_NOW    DL_NOW
  1092. #    endif
  1093. #  endif /* !RTLD_NOW */
  1094. #endif
  1095. #ifndef LT_LAZY_OR_NOW
  1096. #  define LT_LAZY_OR_NOW    0
  1097. #endif /* !LT_LAZY_OR_NOW */
  1098.  
  1099. #if HAVE_DLERROR
  1100. #  define DLERROR(arg)    dlerror ()
  1101. #else
  1102. #  define DLERROR(arg)    LT_DLSTRERROR (arg)
  1103. #endif
  1104.  
  1105. static lt_module
  1106. sys_dl_open (loader_data, filename)
  1107.      lt_user_data loader_data;
  1108.      const char *filename;
  1109. {
  1110.   lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
  1111.  
  1112.   if (!module)
  1113.     {
  1114.       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
  1115.     }
  1116.  
  1117.   return module;
  1118. }
  1119.  
  1120. static int
  1121. sys_dl_close (loader_data, module)
  1122.      lt_user_data loader_data;
  1123.      lt_module module;
  1124. {
  1125.   int errors = 0;
  1126.  
  1127.   if (dlclose (module) != 0)
  1128.     {
  1129.       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
  1130.       ++errors;
  1131.     }
  1132.  
  1133.   return errors;
  1134. }
  1135.  
  1136. static lt_ptr
  1137. sys_dl_sym (loader_data, module, symbol)
  1138.      lt_user_data loader_data;
  1139.      lt_module module;
  1140.      const char *symbol;
  1141. {
  1142.   lt_ptr address = dlsym (module, symbol);
  1143.  
  1144.   if (!address)
  1145.     {
  1146.       LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
  1147.     }
  1148.  
  1149.   return address;
  1150. }
  1151.  
  1152. static struct lt_user_dlloader sys_dl =
  1153.   {
  1154. #  ifdef NEED_USCORE
  1155.     "_",
  1156. #  else
  1157.     0,
  1158. #  endif
  1159.     sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
  1160.  
  1161.  
  1162. #endif /* HAVE_LIBDL */
  1163.  
  1164.  
  1165.  
  1166. /* --- SHL_LOAD() INTERFACE LOADER --- */
  1167.  
  1168. #if HAVE_SHL_LOAD
  1169.  
  1170. /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
  1171.  
  1172. #ifdef HAVE_DL_H
  1173. #  include <dl.h>
  1174. #endif
  1175.  
  1176. /* some flags are missing on some systems, so we provide
  1177.  * harmless defaults.
  1178.  *
  1179.  * Mandatory:
  1180.  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
  1181.  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
  1182.  *
  1183.  * Optionally:
  1184.  * BIND_FIRST       - Place the library at the head of the symbol search
  1185.  *              order.
  1186.  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
  1187.  *              unsatisfied symbols as fatal.  This flag allows
  1188.  *              binding of unsatisfied code symbols to be deferred
  1189.  *              until use.
  1190.  *             [Perl: For certain libraries, like DCE, deferred
  1191.  *             binding often causes run time problems. Adding
  1192.  *             BIND_NONFATAL to BIND_IMMEDIATE still allows
  1193.  *             unresolved references in situations like this.]
  1194.  * BIND_NOSTART       - Do not call the initializer for the shared library
  1195.  *             when the library is loaded, nor on a future call to
  1196.  *             shl_unload().
  1197.  * BIND_VERBOSE       - Print verbose messages concerning possible
  1198.  *             unsatisfied symbols.
  1199.  *
  1200.  * hp9000s700/hp9000s800:
  1201.  * BIND_RESTRICTED - Restrict symbols visible by the library to those
  1202.  *             present at library load time.
  1203.  * DYNAMIC_PATH       - Allow the loader to dynamically search for the
  1204.  *             library specified by the path argument.
  1205.  */
  1206.  
  1207. #ifndef    DYNAMIC_PATH
  1208. #  define DYNAMIC_PATH        0
  1209. #endif
  1210. #ifndef    BIND_RESTRICTED
  1211. #  define BIND_RESTRICTED    0
  1212. #endif
  1213.  
  1214. #define    LT_BIND_FLAGS    (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
  1215.  
  1216. static lt_module
  1217. sys_shl_open (loader_data, filename)
  1218.      lt_user_data loader_data;
  1219.      const char *filename;
  1220. {
  1221.   static shl_t self = (shl_t) 0;
  1222.   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
  1223.  
  1224.   /* Since searching for a symbol against a NULL module handle will also
  1225.      look in everything else that was already loaded and exported with
  1226.      the -E compiler flag, we always cache a handle saved before any
  1227.      modules are loaded.  */
  1228.   if (!self)
  1229.     {
  1230.       lt_ptr address;
  1231.       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
  1232.     }
  1233.  
  1234.   if (!filename)
  1235.     {
  1236.       module = self;
  1237.     }
  1238.   else
  1239.     {
  1240.       module = shl_load (filename, LT_BIND_FLAGS, 0L);
  1241.  
  1242.       if (!module)
  1243.     {
  1244.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1245.     }
  1246.     }
  1247.  
  1248.   return module;
  1249. }
  1250.  
  1251. static int
  1252. sys_shl_close (loader_data, module)
  1253.      lt_user_data loader_data;
  1254.      lt_module module;
  1255. {
  1256.   int errors = 0;
  1257.  
  1258.   if (module && (shl_unload ((shl_t) (module)) != 0))
  1259.     {
  1260.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1261.       ++errors;
  1262.     }
  1263.  
  1264.   return errors;
  1265. }
  1266.  
  1267. static lt_ptr
  1268. sys_shl_sym (loader_data, module, symbol)
  1269.      lt_user_data loader_data;
  1270.      lt_module module;
  1271.      const char *symbol;
  1272. {
  1273.   lt_ptr address = 0;
  1274.  
  1275.   /* sys_shl_open should never return a NULL module handle */
  1276.   if (module == (lt_module) 0)
  1277.   {
  1278.     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  1279.   }
  1280.   else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
  1281.     {
  1282.       if (!address)
  1283.     {
  1284.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1285.     }
  1286.     }
  1287.  
  1288.   return address;
  1289. }
  1290.  
  1291. static struct lt_user_dlloader sys_shl = {
  1292.   0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
  1293. };
  1294.  
  1295. #endif /* HAVE_SHL_LOAD */
  1296.  
  1297.  
  1298.  
  1299.  
  1300. /* --- LOADLIBRARY() INTERFACE LOADER --- */
  1301.  
  1302. #ifdef __WINDOWS__
  1303.  
  1304. /* dynamic linking for Win32 */
  1305.  
  1306. #include <windows.h>
  1307.  
  1308. /* Forward declaration; required to implement handle search below. */
  1309. static lt_dlhandle handles;
  1310.  
  1311. static lt_module
  1312. sys_wll_open (loader_data, filename)
  1313.      lt_user_data loader_data;
  1314.      const char *filename;
  1315. {
  1316.   lt_dlhandle    cur;
  1317.   lt_module    module       = 0;
  1318.   const char   *errormsg   = 0;
  1319.   char           *searchname = 0;
  1320.   char           *ext;
  1321.   char        self_name_buf[MAX_PATH];
  1322.  
  1323.   if (!filename)
  1324.     {
  1325.       /* Get the name of main module */
  1326.       *self_name_buf = 0;
  1327.       GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
  1328.       filename = ext = self_name_buf;
  1329.     }
  1330.   else
  1331.     {
  1332.       ext = strrchr (filename, '.');
  1333.     }
  1334.  
  1335.   if (ext)
  1336.     {
  1337.       /* FILENAME already has an extension. */
  1338.       searchname = lt_estrdup (filename);
  1339.     }
  1340.   else
  1341.     {
  1342.       /* Append a `.' to stop Windows from adding an
  1343.      implicit `.dll' extension. */
  1344.       searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
  1345.       if (searchname)
  1346.     sprintf (searchname, "%s.", filename);
  1347.     }
  1348.   if (!searchname)
  1349.     return 0;
  1350.  
  1351.   {
  1352.     /* Silence dialog from LoadLibrary on some failures.
  1353.        No way to get the error mode, but to set it,
  1354.        so set it twice to preserve any previous flags. */
  1355.     UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1356.     SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
  1357.  
  1358. #if defined(__CYGWIN__)
  1359.     {
  1360.       char wpath[MAX_PATH];
  1361.       cygwin_conv_to_full_win32_path (searchname, wpath);
  1362.       module = LoadLibrary (wpath);
  1363.     }
  1364. #else
  1365.     module = LoadLibrary (searchname);
  1366. #endif
  1367.  
  1368.     /* Restore the error mode. */
  1369.     SetErrorMode(errormode);
  1370.   }
  1371.  
  1372.   LT_DLFREE (searchname);
  1373.  
  1374.   /* libltdl expects this function to fail if it is unable
  1375.      to physically load the library.  Sadly, LoadLibrary
  1376.      will search the loaded libraries for a match and return
  1377.      one of them if the path search load fails.
  1378.  
  1379.      We check whether LoadLibrary is returning a handle to
  1380.      an already loaded module, and simulate failure if we
  1381.      find one. */
  1382.   LT_DLMUTEX_LOCK ();
  1383.   cur = handles;
  1384.   while (cur)
  1385.     {
  1386.       if (!cur->module)
  1387.     {
  1388.       cur = 0;
  1389.       break;
  1390.     }
  1391.  
  1392.       if (cur->module == module)
  1393.     {
  1394.       break;
  1395.     }
  1396.  
  1397.       cur = cur->next;
  1398.   }
  1399.   LT_DLMUTEX_UNLOCK ();
  1400.  
  1401.   if (cur || !module)
  1402.     {
  1403.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1404.       module = 0;
  1405.     }
  1406.  
  1407.   return module;
  1408. }
  1409.  
  1410. static int
  1411. sys_wll_close (loader_data, module)
  1412.      lt_user_data loader_data;
  1413.      lt_module module;
  1414. {
  1415.   int          errors   = 0;
  1416.  
  1417.   if (FreeLibrary(module) == 0)
  1418.     {
  1419.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1420.       ++errors;
  1421.     }
  1422.  
  1423.   return errors;
  1424. }
  1425.  
  1426. static lt_ptr
  1427. sys_wll_sym (loader_data, module, symbol)
  1428.      lt_user_data loader_data;
  1429.      lt_module module;
  1430.      const char *symbol;
  1431. {
  1432.   lt_ptr      address  = GetProcAddress (module, symbol);
  1433.  
  1434.   if (!address)
  1435.     {
  1436.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1437.     }
  1438.  
  1439.   return address;
  1440. }
  1441.  
  1442. static struct lt_user_dlloader sys_wll = {
  1443.   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
  1444. };
  1445.  
  1446. #endif /* __WINDOWS__ */
  1447.  
  1448.  
  1449.  
  1450.  
  1451. /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
  1452.  
  1453.  
  1454. #ifdef __BEOS__
  1455.  
  1456. /* dynamic linking for BeOS */
  1457.  
  1458. #include <kernel/image.h>
  1459.  
  1460. static lt_module
  1461. sys_bedl_open (loader_data, filename)
  1462.      lt_user_data loader_data;
  1463.      const char *filename;
  1464. {
  1465.   image_id image = 0;
  1466.  
  1467.   if (filename)
  1468.     {
  1469.       image = load_add_on (filename);
  1470.     }
  1471.   else
  1472.     {
  1473.       image_info info;
  1474.       int32 cookie = 0;
  1475.       if (get_next_image_info (0, &cookie, &info) == B_OK)
  1476.     image = load_add_on (info.name);
  1477.     }
  1478.  
  1479.   if (image <= 0)
  1480.     {
  1481.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1482.       image = 0;
  1483.     }
  1484.  
  1485.   return (lt_module) image;
  1486. }
  1487.  
  1488. static int
  1489. sys_bedl_close (loader_data, module)
  1490.      lt_user_data loader_data;
  1491.      lt_module module;
  1492. {
  1493.   int errors = 0;
  1494.  
  1495.   if (unload_add_on ((image_id) module) != B_OK)
  1496.     {
  1497.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1498.       ++errors;
  1499.     }
  1500.  
  1501.   return errors;
  1502. }
  1503.  
  1504. static lt_ptr
  1505. sys_bedl_sym (loader_data, module, symbol)
  1506.      lt_user_data loader_data;
  1507.      lt_module module;
  1508.      const char *symbol;
  1509. {
  1510.   lt_ptr address = 0;
  1511.   image_id image = (image_id) module;
  1512.  
  1513.   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
  1514.     {
  1515.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1516.       address = 0;
  1517.     }
  1518.  
  1519.   return address;
  1520. }
  1521.  
  1522. static struct lt_user_dlloader sys_bedl = {
  1523.   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
  1524. };
  1525.  
  1526. #endif /* __BEOS__ */
  1527.  
  1528.  
  1529.  
  1530.  
  1531. /* --- DLD_LINK() INTERFACE LOADER --- */
  1532.  
  1533.  
  1534. #if HAVE_DLD
  1535.  
  1536. /* dynamic linking with dld */
  1537.  
  1538. #if HAVE_DLD_H
  1539. #include <dld.h>
  1540. #endif
  1541.  
  1542. static lt_module
  1543. sys_dld_open (loader_data, filename)
  1544.      lt_user_data loader_data;
  1545.      const char *filename;
  1546. {
  1547.   lt_module module = strdup (filename);
  1548.  
  1549.   if (dld_link (filename) != 0)
  1550.     {
  1551.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1552.       LT_DLFREE (module);
  1553.       module = 0;
  1554.     }
  1555.  
  1556.   return module;
  1557. }
  1558.  
  1559. static int
  1560. sys_dld_close (loader_data, module)
  1561.      lt_user_data loader_data;
  1562.      lt_module module;
  1563. {
  1564.   int errors = 0;
  1565.  
  1566.   if (dld_unlink_by_file ((char*)(module), 1) != 0)
  1567.     {
  1568.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1569.       ++errors;
  1570.     }
  1571.   else
  1572.     {
  1573.       LT_DLFREE (module);
  1574.     }
  1575.  
  1576.   return errors;
  1577. }
  1578.  
  1579. static lt_ptr
  1580. sys_dld_sym (loader_data, module, symbol)
  1581.      lt_user_data loader_data;
  1582.      lt_module module;
  1583.      const char *symbol;
  1584. {
  1585.   lt_ptr address = dld_get_func (symbol);
  1586.  
  1587.   if (!address)
  1588.     {
  1589.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1590.     }
  1591.  
  1592.   return address;
  1593. }
  1594.  
  1595. static struct lt_user_dlloader sys_dld = {
  1596.   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
  1597. };
  1598.  
  1599. #endif /* HAVE_DLD */
  1600.  
  1601. /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
  1602. #if HAVE_DYLD
  1603.  
  1604.  
  1605. #if HAVE_MACH_O_DYLD_H
  1606. #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
  1607. /* Is this correct? Does it still function properly? */
  1608. #define __private_extern__ extern
  1609. #endif
  1610. # include <mach-o/dyld.h>
  1611. #endif
  1612. #include <mach-o/getsect.h>
  1613.  
  1614. /* We have to put some stuff here that isn't in older dyld.h files */
  1615. #ifndef ENUM_DYLD_BOOL
  1616. # define ENUM_DYLD_BOOL
  1617. # undef FALSE
  1618. # undef TRUE
  1619.  enum DYLD_BOOL {
  1620.     FALSE,
  1621.     TRUE
  1622.  };
  1623. #endif
  1624. #ifndef LC_REQ_DYLD
  1625. # define LC_REQ_DYLD 0x80000000
  1626. #endif
  1627. #ifndef LC_LOAD_WEAK_DYLIB
  1628. # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
  1629. #endif
  1630. static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
  1631. static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
  1632. static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
  1633. static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
  1634.  
  1635. #ifndef NSADDIMAGE_OPTION_NONE
  1636. #define NSADDIMAGE_OPTION_NONE                          0x0
  1637. #endif
  1638. #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
  1639. #define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
  1640. #endif
  1641. #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
  1642. #define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
  1643. #endif
  1644. #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
  1645. #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
  1646. #endif
  1647. #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
  1648. #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
  1649. #endif
  1650. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
  1651. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
  1652. #endif
  1653. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1654. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
  1655. #endif
  1656. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
  1657. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
  1658. #endif
  1659. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1660. #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
  1661. #endif
  1662.  
  1663.  
  1664. static const char *
  1665. lt_int_dyld_error(othererror)
  1666.     char* othererror;
  1667. {
  1668. /* return the dyld error string, or the passed in error string if none */
  1669.     NSLinkEditErrors ler;
  1670.     int lerno;
  1671.     const char *errstr;
  1672.     const char *file;
  1673.     NSLinkEditError(&ler,&lerno,&file,&errstr);
  1674.     if (!errstr || !strlen(errstr)) errstr = othererror;
  1675.     return errstr;
  1676. }
  1677.  
  1678. static const struct mach_header *
  1679. lt_int_dyld_get_mach_header_from_nsmodule(module)
  1680.     NSModule module;
  1681. {
  1682. /* There should probably be an apple dyld api for this */
  1683.     int i=_dyld_image_count();
  1684.     int j;
  1685.     const char *modname=NSNameOfModule(module);
  1686.     const struct mach_header *mh=NULL;
  1687.     if (!modname) return NULL;
  1688.     for (j = 0; j < i; j++)
  1689.     {
  1690.         if (!strcmp(_dyld_get_image_name(j),modname))
  1691.         {
  1692.             mh=_dyld_get_image_header(j);
  1693.             break;
  1694.         }
  1695.     }
  1696.     return mh;
  1697. }
  1698.  
  1699. static const char* lt_int_dyld_lib_install_name(mh)
  1700.     const struct mach_header *mh;
  1701. {
  1702. /* NSAddImage is also used to get the loaded image, but it only works if the lib
  1703.    is installed, for uninstalled libs we need to check the install_names against
  1704.    each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
  1705.    different lib was loaded as a result
  1706. */
  1707.     int j;
  1708.     struct load_command *lc;
  1709.     unsigned long offset = sizeof(struct mach_header);
  1710.     const char* retStr=NULL;
  1711.     for (j = 0; j < mh->ncmds; j++)
  1712.     {
  1713.         lc = (struct load_command*)(((unsigned long)mh) + offset);
  1714.         if (LC_ID_DYLIB == lc->cmd)
  1715.         {
  1716.             retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1717.                                     (unsigned long)lc);
  1718.         }
  1719.         offset += lc->cmdsize;
  1720.     }
  1721.     return retStr;
  1722. }
  1723.  
  1724. static const struct mach_header *
  1725. lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
  1726. {
  1727.     int i=_dyld_image_count();
  1728.     int j;
  1729.     const struct mach_header *mh=NULL;
  1730.     const char *id=NULL;
  1731.     for (j = 0; j < i; j++)
  1732.     {
  1733.         id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
  1734.         if ((id) && (!strcmp(id,name)))
  1735.         {
  1736.             mh=_dyld_get_image_header(j);
  1737.             break;
  1738.         }
  1739.     }
  1740.     return mh;
  1741. }
  1742.  
  1743. static NSSymbol
  1744. lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
  1745.     const char *symbol;
  1746.     const struct mach_header *mh;
  1747. {
  1748.     /* Safe to assume our mh is good */
  1749.     int j;
  1750.     struct load_command *lc;
  1751.     unsigned long offset = sizeof(struct mach_header);
  1752.     NSSymbol retSym = 0;
  1753.     const struct mach_header *mh1;
  1754.     if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
  1755.     {
  1756.         for (j = 0; j < mh->ncmds; j++)
  1757.         {
  1758.             lc = (struct load_command*)(((unsigned long)mh) + offset);
  1759.             if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
  1760.             {
  1761.                 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1762.                                         (unsigned long)lc));
  1763.                 if (!mh1)
  1764.                 {
  1765.                     /* Maybe NSAddImage can find it */
  1766.                     mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1767.                                         (unsigned long)lc),
  1768.                                         NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
  1769.                                         NSADDIMAGE_OPTION_WITH_SEARCHING +
  1770.                                         NSADDIMAGE_OPTION_RETURN_ON_ERROR );
  1771.                 }
  1772.                 if (mh1)
  1773.                 {
  1774.                     retSym = ltdl_NSLookupSymbolInImage(mh1,
  1775.                                             symbol,
  1776.                                             NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1777.                                             | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1778.                                             );
  1779.                     if (retSym) break;
  1780.                 }
  1781.             }
  1782.             offset += lc->cmdsize;
  1783.         }
  1784.     }
  1785.     return retSym;
  1786. }
  1787.  
  1788. static int
  1789. sys_dyld_init()
  1790. {
  1791.     int retCode = 0;
  1792.     int err = 0;
  1793.     if (!_dyld_present()) {
  1794.         retCode=1;
  1795.     }
  1796.     else {
  1797.       err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage);
  1798.       err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage);
  1799.       err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage);
  1800.       err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic);
  1801.     }
  1802.  return retCode;
  1803. }
  1804.  
  1805. static lt_module
  1806. sys_dyld_open (loader_data, filename)
  1807.      lt_user_data loader_data;
  1808.      const char *filename;
  1809. {
  1810.     lt_module   module   = 0;
  1811.     NSObjectFileImage ofi = 0;
  1812.     NSObjectFileImageReturnCode ofirc;
  1813.  
  1814.       if (!filename)
  1815.           return (lt_module)-1;
  1816.     ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
  1817.     switch (ofirc)
  1818.     {
  1819.         case NSObjectFileImageSuccess:
  1820.             module = NSLinkModule(ofi, filename,
  1821.                         NSLINKMODULE_OPTION_RETURN_ON_ERROR
  1822.                          | NSLINKMODULE_OPTION_PRIVATE
  1823.                          | NSLINKMODULE_OPTION_BINDNOW);
  1824.             NSDestroyObjectFileImage(ofi);
  1825.             if (module)
  1826.                 ltdl_NSMakePrivateModulePublic(module);
  1827.             break;
  1828.         case NSObjectFileImageInappropriateFile:
  1829.             if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
  1830.             {
  1831.                 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
  1832.                 break;
  1833.             }
  1834.         default:
  1835.             LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
  1836.             return 0;
  1837.     }
  1838.     if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
  1839.   return module;
  1840. }
  1841.  
  1842. static int
  1843. sys_dyld_close (loader_data, module)
  1844.      lt_user_data loader_data;
  1845.      lt_module module;
  1846. {
  1847.     int retCode = 0;
  1848.     int flags = 0;
  1849.     if (module == (lt_module)-1) return 0;
  1850. #ifdef __BIG_ENDIAN__
  1851.       if (((struct mach_header *)module)->magic == MH_MAGIC)
  1852. #else
  1853.     if (((struct mach_header *)module)->magic == MH_CIGAM)
  1854. #endif
  1855.     {
  1856.       LT_DLMUTEX_SETERROR("Can not close a dylib");
  1857.       retCode = 1;
  1858.     }
  1859.     else
  1860.     {
  1861. #if 1
  1862. /* Currently, if a module contains c++ static destructors and it is unloaded, we
  1863.    get a segfault in atexit(), due to compiler and dynamic loader differences of
  1864.    opinion, this works around that.
  1865. */
  1866.         if ((const struct section *)NULL !=
  1867.            getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
  1868.            "__DATA","__mod_term_func"))
  1869.         {
  1870.             flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
  1871.         }
  1872. #endif
  1873. #ifdef __ppc__
  1874.             flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
  1875. #endif
  1876.         if (!NSUnLinkModule(module,flags))
  1877.         {
  1878.             retCode=1;
  1879.             LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
  1880.         }
  1881.     }
  1882.  
  1883.  return retCode;
  1884. }
  1885.  
  1886. static lt_ptr
  1887. sys_dyld_sym (loader_data, module, symbol)
  1888.      lt_user_data loader_data;
  1889.      lt_module module;
  1890.      const char *symbol;
  1891. {
  1892.     lt_ptr address = 0;
  1893.       NSSymbol *nssym = 0;
  1894.       void *unused;
  1895.       const struct mach_header *mh=NULL;
  1896.       char saveError[256] = "Symbol not found";
  1897.       if (module == (lt_module)-1)
  1898.       {
  1899.           _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
  1900.           return address;
  1901.       }
  1902. #ifdef __BIG_ENDIAN__
  1903.       if (((struct mach_header *)module)->magic == MH_MAGIC)
  1904. #else
  1905.     if (((struct mach_header *)module)->magic == MH_CIGAM)
  1906. #endif
  1907.       {
  1908.           if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
  1909.           {
  1910.               mh=module;
  1911.             if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
  1912.             {
  1913.                 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
  1914.                                             symbol,
  1915.                                             NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1916.                                             | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1917.                                             );
  1918.             }
  1919.         }
  1920.  
  1921.       }
  1922.   else {
  1923.     nssym = NSLookupSymbolInModule(module, symbol);
  1924.     }
  1925.     if (!nssym)
  1926.     {
  1927.         strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
  1928.         saveError[255] = 0;
  1929.         if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
  1930.         nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
  1931.     }
  1932.     if (!nssym)
  1933.     {
  1934.         LT_DLMUTEX_SETERROR (saveError);
  1935.         return NULL;
  1936.     }
  1937.     return NSAddressOfSymbol(nssym);
  1938. }
  1939.  
  1940. static struct lt_user_dlloader sys_dyld =
  1941.   { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
  1942.  
  1943.  
  1944. #endif /* HAVE_DYLD */
  1945.  
  1946.  
  1947. /* --- DLPREOPEN() INTERFACE LOADER --- */
  1948.  
  1949.  
  1950. /* emulate dynamic linking using preloaded_symbols */
  1951.  
  1952. typedef struct lt_dlsymlists_t
  1953. {
  1954.   struct lt_dlsymlists_t       *next;
  1955.   const lt_dlsymlist           *syms;
  1956. } lt_dlsymlists_t;
  1957.  
  1958. static    const lt_dlsymlist     *default_preloaded_symbols    = 0;
  1959. static    lt_dlsymlists_t           *preloaded_symbols        = 0;
  1960.  
  1961. static int
  1962. presym_init (loader_data)
  1963.      lt_user_data loader_data;
  1964. {
  1965.   int errors = 0;
  1966.  
  1967.   LT_DLMUTEX_LOCK ();
  1968.  
  1969.   preloaded_symbols = 0;
  1970.   if (default_preloaded_symbols)
  1971.     {
  1972.       errors = lt_dlpreload (default_preloaded_symbols);
  1973.     }
  1974.  
  1975.   LT_DLMUTEX_UNLOCK ();
  1976.  
  1977.   return errors;
  1978. }
  1979.  
  1980. static int
  1981. presym_free_symlists ()
  1982. {
  1983.   lt_dlsymlists_t *lists;
  1984.  
  1985.   LT_DLMUTEX_LOCK ();
  1986.  
  1987.   lists = preloaded_symbols;
  1988.   while (lists)
  1989.     {
  1990.       lt_dlsymlists_t    *tmp = lists;
  1991.  
  1992.       lists = lists->next;
  1993.       LT_DLFREE (tmp);
  1994.     }
  1995.   preloaded_symbols = 0;
  1996.  
  1997.   LT_DLMUTEX_UNLOCK ();
  1998.  
  1999.   return 0;
  2000. }
  2001.  
  2002. static int
  2003. presym_exit (loader_data)
  2004.      lt_user_data loader_data;
  2005. {
  2006.   presym_free_symlists ();
  2007.   return 0;
  2008. }
  2009.  
  2010. static int
  2011. presym_add_symlist (preloaded)
  2012.      const lt_dlsymlist *preloaded;
  2013. {
  2014.   lt_dlsymlists_t *tmp;
  2015.   lt_dlsymlists_t *lists;
  2016.   int           errors   = 0;
  2017.  
  2018.   LT_DLMUTEX_LOCK ();
  2019.  
  2020.   lists = preloaded_symbols;
  2021.   while (lists)
  2022.     {
  2023.       if (lists->syms == preloaded)
  2024.     {
  2025.       goto done;
  2026.     }
  2027.       lists = lists->next;
  2028.     }
  2029.  
  2030.   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
  2031.   if (tmp)
  2032.     {
  2033.       memset (tmp, 0, sizeof(lt_dlsymlists_t));
  2034.       tmp->syms = preloaded;
  2035.       tmp->next = preloaded_symbols;
  2036.       preloaded_symbols = tmp;
  2037.     }
  2038.   else
  2039.     {
  2040.       ++errors;
  2041.     }
  2042.  
  2043.  done:
  2044.   LT_DLMUTEX_UNLOCK ();
  2045.   return errors;
  2046. }
  2047.  
  2048. static lt_module
  2049. presym_open (loader_data, filename)
  2050.      lt_user_data loader_data;
  2051.      const char *filename;
  2052. {
  2053.   lt_dlsymlists_t *lists;
  2054.   lt_module       module = (lt_module) 0;
  2055.  
  2056.   LT_DLMUTEX_LOCK ();
  2057.   lists = preloaded_symbols;
  2058.  
  2059.   if (!lists)
  2060.     {
  2061.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
  2062.       goto done;
  2063.     }
  2064.  
  2065.   /* Can't use NULL as the reflective symbol header, as NULL is
  2066.      used to mark the end of the entire symbol list.  Self-dlpreopened
  2067.      symbols follow this magic number, chosen to be an unlikely
  2068.      clash with a real module name.  */
  2069.   if (!filename)
  2070.     {
  2071.       filename = "@PROGRAM@";
  2072.     }
  2073.  
  2074.   while (lists)
  2075.     {
  2076.       const lt_dlsymlist *syms = lists->syms;
  2077.  
  2078.       while (syms->name)
  2079.     {
  2080.       if (!syms->address && strcmp(syms->name, filename) == 0)
  2081.         {
  2082.           module = (lt_module) syms;
  2083.           goto done;
  2084.         }
  2085.       ++syms;
  2086.     }
  2087.  
  2088.       lists = lists->next;
  2089.     }
  2090.  
  2091.   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  2092.  
  2093.  done:
  2094.   LT_DLMUTEX_UNLOCK ();
  2095.   return module;
  2096. }
  2097.  
  2098. static int
  2099. presym_close (loader_data, module)
  2100.      lt_user_data loader_data;
  2101.      lt_module module;
  2102. {
  2103.   /* Just to silence gcc -Wall */
  2104.   module = 0;
  2105.   return 0;
  2106. }
  2107.  
  2108. static lt_ptr
  2109. presym_sym (loader_data, module, symbol)
  2110.      lt_user_data loader_data;
  2111.      lt_module module;
  2112.      const char *symbol;
  2113. {
  2114.   lt_dlsymlist *syms = (lt_dlsymlist*) module;
  2115.  
  2116.   ++syms;
  2117.   while (syms->address)
  2118.     {
  2119.       if (strcmp(syms->name, symbol) == 0)
  2120.     {
  2121.       return syms->address;
  2122.     }
  2123.  
  2124.     ++syms;
  2125.   }
  2126.  
  2127.   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  2128.  
  2129.   return 0;
  2130. }
  2131.  
  2132. static struct lt_user_dlloader presym = {
  2133.   0, presym_open, presym_close, presym_sym, presym_exit, 0
  2134. };
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140. /* --- DYNAMIC MODULE LOADING --- */
  2141.  
  2142.  
  2143. /* The type of a function used at each iteration of  foreach_dirinpath().  */
  2144. typedef int    foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
  2145.                          lt_ptr data2));
  2146.  
  2147. static    int    foreach_dirinpath     LT_PARAMS((const char *search_path,
  2148.                          const char *base_name,
  2149.                          foreach_callback_func *func,
  2150.                          lt_ptr data1, lt_ptr data2));
  2151.  
  2152. static    int    find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
  2153.                          lt_ptr ignored));
  2154. static    int    find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
  2155.                          lt_ptr ignored));
  2156. static    int    foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
  2157.                          lt_ptr data2));
  2158.  
  2159.  
  2160. static    int     canonicalize_path     LT_PARAMS((const char *path,
  2161.                          char **pcanonical));
  2162. static    int    argzize_path           LT_PARAMS((const char *path,
  2163.                          char **pargz,
  2164.                          size_t *pargz_len));
  2165. static    FILE   *find_file          LT_PARAMS((const char *search_path,
  2166.                          const char *base_name,
  2167.                          char **pdir));
  2168. static    lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
  2169.                          const char *base_name,
  2170.                          lt_dlhandle *handle));
  2171. static    int    find_module          LT_PARAMS((lt_dlhandle *handle,
  2172.                          const char *dir,
  2173.                          const char *libdir,
  2174.                          const char *dlname,
  2175.                          const char *old_name,
  2176.                          int installed));
  2177. static    int    free_vars          LT_PARAMS((char *dlname, char *oldname,
  2178.                          char *libdir, char *deplibs));
  2179. static    int    load_deplibs          LT_PARAMS((lt_dlhandle handle,
  2180.                          char *deplibs));
  2181. static    int    trim              LT_PARAMS((char **dest,
  2182.                          const char *str));
  2183. static    int    try_dlopen          LT_PARAMS((lt_dlhandle *handle,
  2184.                          const char *filename));
  2185. static    int    tryall_dlopen          LT_PARAMS((lt_dlhandle *handle,
  2186.                          const char *filename));
  2187. static    int    unload_deplibs          LT_PARAMS((lt_dlhandle handle));
  2188. static    int    lt_argz_insert          LT_PARAMS((char **pargz,
  2189.                          size_t *pargz_len,
  2190.                          char *before,
  2191.                          const char *entry));
  2192. static    int    lt_argz_insertinorder LT_PARAMS((char **pargz,
  2193.                          size_t *pargz_len,
  2194.                          const char *entry));
  2195. static    int    lt_argz_insertdir     LT_PARAMS((char **pargz,
  2196.                          size_t *pargz_len,
  2197.                          const char *dirnam,
  2198.                          struct dirent *dp));
  2199. static    int    lt_dlpath_insertdir   LT_PARAMS((char **ppath,
  2200.                          char *before,
  2201.                          const char *dir));
  2202. static    int    list_files_by_dir     LT_PARAMS((const char *dirnam,
  2203.                          char **pargz,
  2204.                          size_t *pargz_len));
  2205. static    int    file_not_found          LT_PARAMS((void));
  2206.  
  2207. static    char           *user_search_path= 0;
  2208. static    lt_dlloader    *loaders        = 0;
  2209. static    lt_dlhandle    handles     = 0;
  2210. static    int        initialized     = 0;
  2211.  
  2212. /* Initialize libltdl. */
  2213. int
  2214. lt_dlinit ()
  2215. {
  2216.   int          errors   = 0;
  2217.  
  2218.   LT_DLMUTEX_LOCK ();
  2219.  
  2220.   /* Initialize only at first call. */
  2221.   if (++initialized == 1)
  2222.     {
  2223.       handles = 0;
  2224.       user_search_path = 0; /* empty search path */
  2225.  
  2226. #if HAVE_LIBDL
  2227.       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
  2228. #endif
  2229. #if HAVE_SHL_LOAD
  2230.       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
  2231. #endif
  2232. #ifdef __WINDOWS__
  2233.       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
  2234. #endif
  2235. #ifdef __BEOS__
  2236.       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
  2237. #endif
  2238. #if HAVE_DLD
  2239.       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
  2240. #endif
  2241. #if HAVE_DYLD
  2242.        errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
  2243.        errors += sys_dyld_init();
  2244. #endif
  2245.       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
  2246.  
  2247.       if (presym_init (presym.dlloader_data))
  2248.     {
  2249.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
  2250.       ++errors;
  2251.     }
  2252.       else if (errors != 0)
  2253.     {
  2254.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
  2255.       ++errors;
  2256.     }
  2257.     }
  2258.  
  2259.   LT_DLMUTEX_UNLOCK ();
  2260.  
  2261.   return errors;
  2262. }
  2263.  
  2264. int
  2265. lt_dlpreload (preloaded)
  2266.      const lt_dlsymlist *preloaded;
  2267. {
  2268.   int errors = 0;
  2269.  
  2270.   if (preloaded)
  2271.     {
  2272.       errors = presym_add_symlist (preloaded);
  2273.     }
  2274.   else
  2275.     {
  2276.       presym_free_symlists();
  2277.  
  2278.       LT_DLMUTEX_LOCK ();
  2279.       if (default_preloaded_symbols)
  2280.     {
  2281.       errors = lt_dlpreload (default_preloaded_symbols);
  2282.     }
  2283.       LT_DLMUTEX_UNLOCK ();
  2284.     }
  2285.  
  2286.   return errors;
  2287. }
  2288.  
  2289. int
  2290. lt_dlpreload_default (preloaded)
  2291.      const lt_dlsymlist *preloaded;
  2292. {
  2293.   LT_DLMUTEX_LOCK ();
  2294.   default_preloaded_symbols = preloaded;
  2295.   LT_DLMUTEX_UNLOCK ();
  2296.   return 0;
  2297. }
  2298.  
  2299. int
  2300. lt_dlexit ()
  2301. {
  2302.   /* shut down libltdl */
  2303.   lt_dlloader *loader;
  2304.   int           errors   = 0;
  2305.  
  2306.   LT_DLMUTEX_LOCK ();
  2307.   loader = loaders;
  2308.  
  2309.   if (!initialized)
  2310.     {
  2311.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
  2312.       ++errors;
  2313.       goto done;
  2314.     }
  2315.  
  2316.   /* shut down only at last call. */
  2317.   if (--initialized == 0)
  2318.     {
  2319.       int    level;
  2320.  
  2321.       while (handles && LT_DLIS_RESIDENT (handles))
  2322.     {
  2323.       handles = handles->next;
  2324.     }
  2325.  
  2326.       /* close all modules */
  2327.       for (level = 1; handles; ++level)
  2328.     {
  2329.       lt_dlhandle cur = handles;
  2330.       int saw_nonresident = 0;
  2331.  
  2332.       while (cur)
  2333.         {
  2334.           lt_dlhandle tmp = cur;
  2335.           cur = cur->next;
  2336.           if (!LT_DLIS_RESIDENT (tmp))
  2337.         saw_nonresident = 1;
  2338.           if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
  2339.         {
  2340.           if (lt_dlclose (tmp))
  2341.             {
  2342.               ++errors;
  2343.             }
  2344.         }
  2345.         }
  2346.       /* done if only resident modules are left */
  2347.       if (!saw_nonresident)
  2348.         break;
  2349.     }
  2350.  
  2351.       /* close all loaders */
  2352.       while (loader)
  2353.     {
  2354.       lt_dlloader *next = loader->next;
  2355.       lt_user_data data = loader->dlloader_data;
  2356.       if (loader->dlloader_exit && loader->dlloader_exit (data))
  2357.         {
  2358.           ++errors;
  2359.         }
  2360.  
  2361.       LT_DLMEM_REASSIGN (loader, next);
  2362.     }
  2363.       loaders = 0;
  2364.     }
  2365.  
  2366.  done:
  2367.   LT_DLMUTEX_UNLOCK ();
  2368.   return errors;
  2369. }
  2370.  
  2371. static int
  2372. tryall_dlopen (handle, filename)
  2373.      lt_dlhandle *handle;
  2374.      const char *filename;
  2375. {
  2376.   lt_dlhandle     cur;
  2377.   lt_dlloader   *loader;
  2378.   const char    *saved_error;
  2379.   int         errors        = 0;
  2380.  
  2381.   LT_DLMUTEX_GETERROR (saved_error);
  2382.   LT_DLMUTEX_LOCK ();
  2383.  
  2384.   cur     = handles;
  2385.   loader = loaders;
  2386.  
  2387.   /* check whether the module was already opened */
  2388.   while (cur)
  2389.     {
  2390.       /* try to dlopen the program itself? */
  2391.       if (!cur->info.filename && !filename)
  2392.     {
  2393.       break;
  2394.     }
  2395.  
  2396.       if (cur->info.filename && filename
  2397.       && strcmp (cur->info.filename, filename) == 0)
  2398.     {
  2399.       break;
  2400.     }
  2401.  
  2402.       cur = cur->next;
  2403.     }
  2404.  
  2405.   if (cur)
  2406.     {
  2407.       ++cur->info.ref_count;
  2408.       *handle = cur;
  2409.       goto done;
  2410.     }
  2411.  
  2412.   cur = *handle;
  2413.   if (filename)
  2414.     {
  2415.       /* Comment out the check of file permissions using access.
  2416.      This call seems to always return -1 with error EACCES.
  2417.       */
  2418.       /* We need to catch missing file errors early so that
  2419.      file_not_found() can detect what happened.
  2420.       if (access (filename, R_OK) != 0)
  2421.     {
  2422.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  2423.       ++errors;
  2424.       goto done;
  2425.     } */
  2426.  
  2427.       cur->info.filename = lt_estrdup (filename);
  2428.       if (!cur->info.filename)
  2429.     {
  2430.       ++errors;
  2431.       goto done;
  2432.     }
  2433.     }
  2434.   else
  2435.     {
  2436.       cur->info.filename = 0;
  2437.     }
  2438.  
  2439.   while (loader)
  2440.     {
  2441.       lt_user_data data = loader->dlloader_data;
  2442.  
  2443.       cur->module = loader->module_open (data, filename);
  2444.  
  2445.       if (cur->module != 0)
  2446.     {
  2447.       break;
  2448.     }
  2449.       loader = loader->next;
  2450.     }
  2451.  
  2452.   if (!loader)
  2453.     {
  2454.       LT_DLFREE (cur->info.filename);
  2455.       ++errors;
  2456.       goto done;
  2457.     }
  2458.  
  2459.   cur->loader    = loader;
  2460.   LT_DLMUTEX_SETERROR (saved_error);
  2461.  
  2462.  done:
  2463.   LT_DLMUTEX_UNLOCK ();
  2464.  
  2465.   return errors;
  2466. }
  2467.  
  2468. static int
  2469. tryall_dlopen_module (handle, prefix, dirname, dlname)
  2470.      lt_dlhandle *handle;
  2471.      const char *prefix;
  2472.      const char *dirname;
  2473.      const char *dlname;
  2474. {
  2475.   int      error    = 0;
  2476.   char     *filename    = 0;
  2477.   size_t   filename_len    = 0;
  2478.   size_t   dirname_len    = LT_STRLEN (dirname);
  2479.  
  2480.   assert (handle);
  2481.   assert (dirname);
  2482.   assert (dlname);
  2483. #ifdef LT_DIRSEP_CHAR
  2484.   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
  2485.      should make it into this function:  */
  2486.   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
  2487. #endif
  2488.  
  2489.   if (dirname_len > 0)
  2490.     if (dirname[dirname_len -1] == '/')
  2491.       --dirname_len;
  2492.   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
  2493.  
  2494.   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
  2495.      The PREFIX (if any) is handled below.  */
  2496.   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
  2497.   if (!filename)
  2498.     return 1;
  2499.  
  2500.   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
  2501.  
  2502.   /* Now that we have combined DIRNAME and MODULENAME, if there is
  2503.      also a PREFIX to contend with, simply recurse with the arguments
  2504.      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
  2505.   if (prefix)
  2506.     {
  2507.       error += tryall_dlopen_module (handle,
  2508.                      (const char *) 0, prefix, filename);
  2509.     }
  2510.   else if (tryall_dlopen (handle, filename) != 0)
  2511.     {
  2512.       ++error;
  2513.     }
  2514.  
  2515.   LT_DLFREE (filename);
  2516.   return error;
  2517. }
  2518.  
  2519. static int
  2520. find_module (handle, dir, libdir, dlname, old_name, installed)
  2521.      lt_dlhandle *handle;
  2522.      const char *dir;
  2523.      const char *libdir;
  2524.      const char *dlname;
  2525.      const char *old_name;
  2526.      int installed;
  2527. {
  2528.   /* Try to open the old library first; if it was dlpreopened,
  2529.      we want the preopened version of it, even if a dlopenable
  2530.      module is available.  */
  2531.   if (old_name && tryall_dlopen (handle, old_name) == 0)
  2532.     {
  2533.       return 0;
  2534.     }
  2535.  
  2536.   /* Try to open the dynamic library.  */
  2537.   if (dlname)
  2538.     {
  2539.       /* try to open the installed module */
  2540.       if (installed && libdir)
  2541.     {
  2542.       if (tryall_dlopen_module (handle,
  2543.                     (const char *) 0, libdir, dlname) == 0)
  2544.         return 0;
  2545.     }
  2546.  
  2547.       /* try to open the not-installed module */
  2548.       if (!installed)
  2549.     {
  2550.       if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
  2551.         return 0;
  2552.     }
  2553.  
  2554.       /* maybe it was moved to another directory */
  2555.       {
  2556.       if (dir && (tryall_dlopen_module (handle,
  2557.                     (const char *) 0, dir, dlname) == 0))
  2558.         return 0;
  2559.       }
  2560.     }
  2561.  
  2562.   return 1;
  2563. }
  2564.  
  2565.  
  2566. static int
  2567. canonicalize_path (path, pcanonical)
  2568.      const char *path;
  2569.      char **pcanonical;
  2570. {
  2571.   char *canonical = 0;
  2572.  
  2573.   assert (path && *path);
  2574.   assert (pcanonical);
  2575.  
  2576.   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
  2577.   if (!canonical)
  2578.     return 1;
  2579.  
  2580.   {
  2581.     size_t dest = 0;
  2582.     size_t src;
  2583.     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
  2584.       {
  2585.     /* Path separators are not copied to the beginning or end of
  2586.        the destination, or if another separator would follow
  2587.        immediately.  */
  2588.     if (path[src] == LT_PATHSEP_CHAR)
  2589.       {
  2590.         if ((dest == 0)
  2591.         || (path[1+ src] == LT_PATHSEP_CHAR)
  2592.         || (path[1+ src] == LT_EOS_CHAR))
  2593.           continue;
  2594.       }
  2595.  
  2596.     /* Anything other than a directory separator is copied verbatim.  */
  2597.     if ((path[src] != '/')
  2598. #ifdef LT_DIRSEP_CHAR
  2599.         && (path[src] != LT_DIRSEP_CHAR)
  2600. #endif
  2601.         )
  2602.       {
  2603.         canonical[dest++] = path[src];
  2604.       }
  2605.     /* Directory separators are converted and copied only if they are
  2606.        not at the end of a path -- i.e. before a path separator or
  2607.        NULL terminator.  */
  2608.     else if ((path[1+ src] != LT_PATHSEP_CHAR)
  2609.          && (path[1+ src] != LT_EOS_CHAR)
  2610. #ifdef LT_DIRSEP_CHAR
  2611.          && (path[1+ src] != LT_DIRSEP_CHAR)
  2612. #endif
  2613.          && (path[1+ src] != '/'))
  2614.       {
  2615.         canonical[dest++] = '/';
  2616.       }
  2617.       }
  2618.  
  2619.     /* Add an end-of-string marker at the end.  */
  2620.     canonical[dest] = LT_EOS_CHAR;
  2621.   }
  2622.  
  2623.   /* Assign new value.  */
  2624.   *pcanonical = canonical;
  2625.  
  2626.   return 0;
  2627. }
  2628.  
  2629. static int
  2630. argzize_path (path, pargz, pargz_len)
  2631.      const char *path;
  2632.      char **pargz;
  2633.      size_t *pargz_len;
  2634. {
  2635.   error_t error;
  2636.  
  2637.   assert (path);
  2638.   assert (pargz);
  2639.   assert (pargz_len);
  2640.  
  2641.   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
  2642.     {
  2643.       switch (error)
  2644.     {
  2645.     case ENOMEM:
  2646.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  2647.       break;
  2648.     default:
  2649.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
  2650.       break;
  2651.     }
  2652.  
  2653.       return 1;
  2654.     }
  2655.  
  2656.   return 0;
  2657. }
  2658.  
  2659. /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
  2660.    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
  2661.    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
  2662.    it is appended to each SEARCH_PATH element before FUNC is called.  */
  2663. static int
  2664. foreach_dirinpath (search_path, base_name, func, data1, data2)
  2665.      const char *search_path;
  2666.      const char *base_name;
  2667.      foreach_callback_func *func;
  2668.      lt_ptr data1;
  2669.      lt_ptr data2;
  2670. {
  2671.   int     result        = 0;
  2672.   int     filenamesize    = 0;
  2673.   size_t lenbase    = LT_STRLEN (base_name);
  2674.   size_t argz_len    = 0;
  2675.   char *argz        = 0;
  2676.   char *filename    = 0;
  2677.   char *canonical    = 0;
  2678.  
  2679.   LT_DLMUTEX_LOCK ();
  2680.  
  2681.   if (!search_path || !*search_path)
  2682.     {
  2683.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  2684.       goto cleanup;
  2685.     }
  2686.  
  2687.   if (canonicalize_path (search_path, &canonical) != 0)
  2688.     goto cleanup;
  2689.  
  2690.   if (argzize_path (canonical, &argz, &argz_len) != 0)
  2691.     goto cleanup;
  2692.  
  2693.   {
  2694.     char *dir_name = 0;
  2695.     while ((dir_name = argz_next (argz, argz_len, dir_name)))
  2696.       {
  2697.     size_t lendir = LT_STRLEN (dir_name);
  2698.  
  2699.     if (lendir +1 +lenbase >= filenamesize)
  2700.     {
  2701.       LT_DLFREE (filename);
  2702.       filenamesize    = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
  2703.       filename    = LT_EMALLOC (char, filenamesize);
  2704.       if (!filename)
  2705.         goto cleanup;
  2706.     }
  2707.  
  2708.     assert (filenamesize > lendir);
  2709.     strcpy (filename, dir_name);
  2710.  
  2711.     if (base_name && *base_name)
  2712.       {
  2713.         if (filename[lendir -1] != '/')
  2714.           filename[lendir++] = '/';
  2715.         strcpy (filename +lendir, base_name);
  2716.       }
  2717.  
  2718.     if ((result = (*func) (filename, data1, data2)))
  2719.       {
  2720.         break;
  2721.       }
  2722.       }
  2723.   }
  2724.  
  2725.  cleanup:
  2726.   LT_DLFREE (argz);
  2727.   LT_DLFREE (canonical);
  2728.   LT_DLFREE (filename);
  2729.  
  2730.   LT_DLMUTEX_UNLOCK ();
  2731.  
  2732.   return result;
  2733. }
  2734.  
  2735. /* If FILEPATH can be opened, store the name of the directory component
  2736.    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
  2737.    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
  2738. static int
  2739. find_file_callback (filename, data1, data2)
  2740.      char *filename;
  2741.      lt_ptr data1;
  2742.      lt_ptr data2;
  2743. {
  2744.   char         **pdir    = (char **) data1;
  2745.   FILE         **pfile    = (FILE **) data2;
  2746.   int         is_done    = 0;
  2747.  
  2748.   assert (filename && *filename);
  2749.   assert (pdir);
  2750.   assert (pfile);
  2751.  
  2752.   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
  2753.     {
  2754.       char *dirend = strrchr (filename, '/');
  2755.  
  2756.       if (dirend > filename)
  2757.     *dirend   = LT_EOS_CHAR;
  2758.  
  2759.       LT_DLFREE (*pdir);
  2760.       *pdir   = lt_estrdup (filename);
  2761.       is_done = (*pdir == 0) ? -1 : 1;
  2762.     }
  2763.  
  2764.   return is_done;
  2765. }
  2766.  
  2767. static FILE *
  2768. find_file (search_path, base_name, pdir)
  2769.      const char *search_path;
  2770.      const char *base_name;
  2771.      char **pdir;
  2772. {
  2773.   FILE *file = 0;
  2774.  
  2775.   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
  2776.  
  2777.   return file;
  2778. }
  2779.  
  2780. static int
  2781. find_handle_callback (filename, data, ignored)
  2782.      char *filename;
  2783.      lt_ptr data;
  2784.      lt_ptr ignored;
  2785. {
  2786.   lt_dlhandle  *handle        = (lt_dlhandle *) data;
  2787.   int        notfound    = access (filename, R_OK);
  2788.  
  2789.   /* Bail out if file cannot be read...  */
  2790.   if (notfound)
  2791.     return 0;
  2792.  
  2793.   /* Try to dlopen the file, but do not continue searching in any
  2794.      case.  */
  2795.   if (tryall_dlopen (handle, filename) != 0)
  2796.     *handle = 0;
  2797.  
  2798.   return 1;
  2799. }
  2800.  
  2801. /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
  2802.    found but could not be opened, *HANDLE will be set to 0.  */
  2803. static lt_dlhandle *
  2804. find_handle (search_path, base_name, handle)
  2805.      const char *search_path;
  2806.      const char *base_name;
  2807.      lt_dlhandle *handle;
  2808. {
  2809.   if (!search_path)
  2810.     return 0;
  2811.  
  2812.   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
  2813.               handle, 0))
  2814.     return 0;
  2815.  
  2816.   return handle;
  2817. }
  2818.  
  2819. static int
  2820. load_deplibs (handle, deplibs)
  2821.      lt_dlhandle handle;
  2822.      char *deplibs;
  2823. {
  2824. #if LTDL_DLOPEN_DEPLIBS
  2825.   char    *p, *save_search_path = 0;
  2826.   int   depcount = 0;
  2827.   int    i;
  2828.   char    **names = 0;
  2829. #endif
  2830.   int    errors = 0;
  2831.  
  2832.   handle->depcount = 0;
  2833.  
  2834. #if LTDL_DLOPEN_DEPLIBS
  2835.   if (!deplibs)
  2836.     {
  2837.       return errors;
  2838.     }
  2839.   ++errors;
  2840.  
  2841.   LT_DLMUTEX_LOCK ();
  2842.   if (user_search_path)
  2843.     {
  2844.       save_search_path = lt_estrdup (user_search_path);
  2845.       if (!save_search_path)
  2846.     goto cleanup;
  2847.     }
  2848.  
  2849.   /* extract search paths and count deplibs */
  2850.   p = deplibs;
  2851.   while (*p)
  2852.     {
  2853.       if (!isspace ((int) *p))
  2854.     {
  2855.       char *end = p+1;
  2856.       while (*end && !isspace((int) *end))
  2857.         {
  2858.           ++end;
  2859.         }
  2860.  
  2861.       if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
  2862.         {
  2863.           char save = *end;
  2864.           *end = 0; /* set a temporary string terminator */
  2865.           if (lt_dladdsearchdir(p+2))
  2866.         {
  2867.           goto cleanup;
  2868.         }
  2869.           *end = save;
  2870.         }
  2871.       else
  2872.         {
  2873.           ++depcount;
  2874.         }
  2875.  
  2876.       p = end;
  2877.     }
  2878.       else
  2879.     {
  2880.       ++p;
  2881.     }
  2882.     }
  2883.  
  2884.   if (!depcount)
  2885.     {
  2886.       errors = 0;
  2887.       goto cleanup;
  2888.     }
  2889.  
  2890.   names = LT_EMALLOC (char *, depcount * sizeof (char*));
  2891.   if (!names)
  2892.     goto cleanup;
  2893.  
  2894.   /* now only extract the actual deplibs */
  2895.   depcount = 0;
  2896.   p = deplibs;
  2897.   while (*p)
  2898.     {
  2899.       if (isspace ((int) *p))
  2900.     {
  2901.       ++p;
  2902.     }
  2903.       else
  2904.     {
  2905.       char *end = p+1;
  2906.       while (*end && !isspace ((int) *end))
  2907.         {
  2908.           ++end;
  2909.         }
  2910.  
  2911.       if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
  2912.         {
  2913.           char *name;
  2914.           char save = *end;
  2915.           *end = 0; /* set a temporary string terminator */
  2916.           if (strncmp(p, "-l", 2) == 0)
  2917.         {
  2918.           size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
  2919.           name = LT_EMALLOC (char, 1+ name_len);
  2920.           if (name)
  2921.             sprintf (name, "lib%s", p+2);
  2922.         }
  2923.           else
  2924.         name = lt_estrdup(p);
  2925.  
  2926.           if (!name)
  2927.         goto cleanup_names;
  2928.  
  2929.           names[depcount++] = name;
  2930.           *end = save;
  2931.         }
  2932.       p = end;
  2933.     }
  2934.     }
  2935.  
  2936.   /* load the deplibs (in reverse order)
  2937.      At this stage, don't worry if the deplibs do not load correctly,
  2938.      they may already be statically linked into the loading application
  2939.      for instance.  There will be a more enlightening error message
  2940.      later on if the loaded module cannot resolve all of its symbols.  */
  2941.   if (depcount)
  2942.     {
  2943.       int    j = 0;
  2944.  
  2945.       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
  2946.       if (!handle->deplibs)
  2947.     goto cleanup;
  2948.  
  2949.       for (i = 0; i < depcount; ++i)
  2950.     {
  2951.       handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
  2952.       if (handle->deplibs[j])
  2953.         {
  2954.           ++j;
  2955.         }
  2956.     }
  2957.  
  2958.       handle->depcount    = j;    /* Number of successfully loaded deplibs */
  2959.       errors        = 0;
  2960.     }
  2961.  
  2962.  cleanup_names:
  2963.   for (i = 0; i < depcount; ++i)
  2964.     {
  2965.       LT_DLFREE (names[i]);
  2966.     }
  2967.  
  2968.  cleanup:
  2969.   LT_DLFREE (names);
  2970.   /* restore the old search path */
  2971.   if (user_search_path) {
  2972.     LT_DLFREE (user_search_path);
  2973.     user_search_path = save_search_path;
  2974.   }
  2975.   LT_DLMUTEX_UNLOCK ();
  2976.  
  2977. #endif
  2978.  
  2979.   return errors;
  2980. }
  2981.  
  2982. static int
  2983. unload_deplibs (handle)
  2984.      lt_dlhandle handle;
  2985. {
  2986.   int i;
  2987.   int errors = 0;
  2988.  
  2989.   if (handle->depcount)
  2990.     {
  2991.       for (i = 0; i < handle->depcount; ++i)
  2992.     {
  2993.       if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
  2994.         {
  2995.           errors += lt_dlclose (handle->deplibs[i]);
  2996.         }
  2997.     }
  2998.     }
  2999.  
  3000.   return errors;
  3001. }
  3002.  
  3003. static int
  3004. trim (dest, str)
  3005.      char **dest;
  3006.      const char *str;
  3007. {
  3008.   /* remove the leading and trailing "'" from str
  3009.      and store the result in dest */
  3010.   const char *end   = strrchr (str, '\'');
  3011.   size_t len        = LT_STRLEN (str);
  3012.   char *tmp;
  3013.  
  3014.   LT_DLFREE (*dest);
  3015.  
  3016.   if (!end)
  3017.     return 1;
  3018.  
  3019.   if (len > 3 && str[0] == '\'')
  3020.     {
  3021.       tmp = LT_EMALLOC (char, end - str);
  3022.       if (!tmp)
  3023.     return 1;
  3024.  
  3025.       strncpy(tmp, &str[1], (end - str) - 1);
  3026.       tmp[len-3] = LT_EOS_CHAR;
  3027.       *dest = tmp;
  3028.     }
  3029.   else
  3030.     {
  3031.       *dest = 0;
  3032.     }
  3033.  
  3034.   return 0;
  3035. }
  3036.  
  3037. static int
  3038. free_vars (dlname, oldname, libdir, deplibs)
  3039.      char *dlname;
  3040.      char *oldname;
  3041.      char *libdir;
  3042.      char *deplibs;
  3043. {
  3044.   LT_DLFREE (dlname);
  3045.   LT_DLFREE (oldname);
  3046.   LT_DLFREE (libdir);
  3047.   LT_DLFREE (deplibs);
  3048.  
  3049.   return 0;
  3050. }
  3051.  
  3052. static int
  3053. try_dlopen (phandle, filename)
  3054.      lt_dlhandle *phandle;
  3055.      const char *filename;
  3056. {
  3057.   const char *    ext        = 0;
  3058.   const char *    saved_error    = 0;
  3059.   char *    canonical    = 0;
  3060.   char *    base_name    = 0;
  3061.   char *    dir        = 0;
  3062.   char *    name        = 0;
  3063.   int        errors        = 0;
  3064.   lt_dlhandle    newhandle;
  3065.  
  3066.   assert (phandle);
  3067.   assert (*phandle == 0);
  3068.  
  3069.   LT_DLMUTEX_GETERROR (saved_error);
  3070.  
  3071.   /* dlopen self? */
  3072.   if (!filename)
  3073.     {
  3074.       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
  3075.       if (*phandle == 0)
  3076.     return 1;
  3077.  
  3078.       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
  3079.       newhandle    = *phandle;
  3080.  
  3081.       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
  3082.       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
  3083.  
  3084.       if (tryall_dlopen (&newhandle, 0) != 0)
  3085.     {
  3086.       LT_DLFREE (*phandle);
  3087.       return 1;
  3088.     }
  3089.  
  3090.       goto register_handle;
  3091.     }
  3092.  
  3093.   assert (filename && *filename);
  3094.  
  3095.   /* Doing this immediately allows internal functions to safely
  3096.      assume only canonicalized paths are passed.  */
  3097.   if (canonicalize_path (filename, &canonical) != 0)
  3098.     {
  3099.       ++errors;
  3100.       goto cleanup;
  3101.     }
  3102.  
  3103.   /* If the canonical module name is a path (relative or absolute)
  3104.      then split it into a directory part and a name part.  */
  3105.   base_name = strrchr (canonical, '/');
  3106.   if (base_name)
  3107.     {
  3108.       size_t dirlen = (1+ base_name) - canonical;
  3109.  
  3110.       dir = LT_EMALLOC (char, 1+ dirlen);
  3111.       if (!dir)
  3112.     {
  3113.       ++errors;
  3114.       goto cleanup;
  3115.     }
  3116.  
  3117.       strncpy (dir, canonical, dirlen);
  3118.       dir[dirlen] = LT_EOS_CHAR;
  3119.  
  3120.       ++base_name;
  3121.     }
  3122.   else
  3123.     base_name = canonical;
  3124.  
  3125.   assert (base_name && *base_name);
  3126.  
  3127.   /* Check whether we are opening a libtool module (.la extension).  */
  3128.   ext = strrchr (base_name, '.');
  3129.   if (ext && strcmp (ext, archive_ext) == 0)
  3130.     {
  3131.       /* this seems to be a libtool module */
  3132.       FILE *    file     = 0;
  3133.       char *    dlname     = 0;
  3134.       char *    old_name = 0;
  3135.       char *    libdir     = 0;
  3136.       char *    deplibs     = 0;
  3137.       char *    line     = 0;
  3138.       size_t    line_len;
  3139.  
  3140.       /* if we can't find the installed flag, it is probably an
  3141.      installed libtool archive, produced with an old version
  3142.      of libtool */
  3143.       int    installed = 1;
  3144.  
  3145.       /* extract the module name from the file name */
  3146.       name = LT_EMALLOC (char, ext - base_name + 1);
  3147.       if (!name)
  3148.     {
  3149.       ++errors;
  3150.       goto cleanup;
  3151.     }
  3152.  
  3153.       /* canonicalize the module name */
  3154.       {
  3155.         size_t i;
  3156.         for (i = 0; i < ext - base_name; ++i)
  3157.       {
  3158.         if (isalnum ((int)(base_name[i])))
  3159.           {
  3160.             name[i] = base_name[i];
  3161.           }
  3162.         else
  3163.           {
  3164.             name[i] = '_';
  3165.           }
  3166.       }
  3167.         name[ext - base_name] = LT_EOS_CHAR;
  3168.       }
  3169.  
  3170.       /* Now try to open the .la file.  If there is no directory name
  3171.          component, try to find it first in user_search_path and then other
  3172.          prescribed paths.  Otherwise (or in any case if the module was not
  3173.          yet found) try opening just the module name as passed.  */
  3174.       if (!dir)
  3175.     {
  3176.       const char *search_path;
  3177.  
  3178.       LT_DLMUTEX_LOCK ();
  3179.       search_path = user_search_path;
  3180.       if (search_path)
  3181.         file = find_file (user_search_path, base_name, &dir);
  3182.       LT_DLMUTEX_UNLOCK ();
  3183.  
  3184.       if (!file)
  3185.         {
  3186.           search_path = getenv (LTDL_SEARCHPATH_VAR);
  3187.           if (search_path)
  3188.         file = find_file (search_path, base_name, &dir);
  3189.         }
  3190.  
  3191. #ifdef LTDL_SHLIBPATH_VAR
  3192.       if (!file)
  3193.         {
  3194.           search_path = getenv (LTDL_SHLIBPATH_VAR);
  3195.           if (search_path)
  3196.         file = find_file (search_path, base_name, &dir);
  3197.         }
  3198. #endif
  3199. #ifdef LTDL_SYSSEARCHPATH
  3200.       if (!file && sys_search_path)
  3201.         {
  3202.           file = find_file (sys_search_path, base_name, &dir);
  3203.         }
  3204. #endif
  3205.     }
  3206.       if (!file)
  3207.     {
  3208.       file = fopen (filename, LT_READTEXT_MODE);
  3209.     }
  3210.  
  3211.       /* If we didn't find the file by now, it really isn't there.  Set
  3212.      the status flag, and bail out.  */
  3213.       if (!file)
  3214.     {
  3215.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  3216.       ++errors;
  3217.       goto cleanup;
  3218.     }
  3219.  
  3220.       line_len = LT_FILENAME_MAX;
  3221.       line = LT_EMALLOC (char, line_len);
  3222.       if (!line)
  3223.     {
  3224.       fclose (file);
  3225.       ++errors;
  3226.       goto cleanup;
  3227.     }
  3228.  
  3229.       /* read the .la file */
  3230.       while (!feof (file))
  3231.     {
  3232.       if (!fgets (line, (int) line_len, file))
  3233.         {
  3234.           break;
  3235.         }
  3236.  
  3237.       /* Handle the case where we occasionally need to read a line
  3238.          that is longer than the initial buffer size.  */
  3239.       while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
  3240.         {
  3241.           line = LT_DLREALLOC (char, line, line_len *2);
  3242.           if (!fgets (&line[line_len -1], (int) line_len +1, file))
  3243.         {
  3244.           break;
  3245.         }
  3246.           line_len *= 2;
  3247.         }
  3248.  
  3249.       if (line[0] == '\n' || line[0] == '#')
  3250.         {
  3251.           continue;
  3252.         }
  3253.  
  3254. #undef  STR_DLNAME
  3255. #define STR_DLNAME    "dlname="
  3256.       if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
  3257.         {
  3258.           errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
  3259.         }
  3260.  
  3261. #undef  STR_OLD_LIBRARY
  3262. #define STR_OLD_LIBRARY    "old_library="
  3263.       else if (strncmp (line, STR_OLD_LIBRARY,
  3264.                 sizeof (STR_OLD_LIBRARY) - 1) == 0)
  3265.         {
  3266.           errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
  3267.         }
  3268. #undef  STR_LIBDIR
  3269. #define STR_LIBDIR    "libdir="
  3270.       else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
  3271.         {
  3272.           errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
  3273.         }
  3274.  
  3275. #undef  STR_DL_DEPLIBS
  3276. #define STR_DL_DEPLIBS    "dependency_libs="
  3277.       else if (strncmp (line, STR_DL_DEPLIBS,
  3278.                 sizeof (STR_DL_DEPLIBS) - 1) == 0)
  3279.         {
  3280.           errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
  3281.         }
  3282.       else if (strcmp (line, "installed=yes\n") == 0)
  3283.         {
  3284.           installed = 1;
  3285.         }
  3286.       else if (strcmp (line, "installed=no\n") == 0)
  3287.         {
  3288.           installed = 0;
  3289.         }
  3290.  
  3291. #undef  STR_LIBRARY_NAMES
  3292. #define STR_LIBRARY_NAMES "library_names="
  3293.       else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
  3294.                     sizeof (STR_LIBRARY_NAMES) - 1) == 0)
  3295.         {
  3296.           char *last_libname;
  3297.           errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
  3298.           if (!errors
  3299.           && dlname
  3300.           && (last_libname = strrchr (dlname, ' ')) != 0)
  3301.         {
  3302.           last_libname = lt_estrdup (last_libname + 1);
  3303.           if (!last_libname)
  3304.             {
  3305.               ++errors;
  3306.               goto cleanup;
  3307.             }
  3308.           LT_DLMEM_REASSIGN (dlname, last_libname);
  3309.         }
  3310.         }
  3311.  
  3312.       if (errors)
  3313.         break;
  3314.     }
  3315.  
  3316.       fclose (file);
  3317.       LT_DLFREE (line);
  3318.  
  3319.       /* allocate the handle */
  3320.       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
  3321.       if (*phandle == 0)
  3322.     ++errors;
  3323.  
  3324.       if (errors)
  3325.     {
  3326.       free_vars (dlname, old_name, libdir, deplibs);
  3327.       LT_DLFREE (*phandle);
  3328.       goto cleanup;
  3329.     }
  3330.  
  3331.       assert (*phandle);
  3332.  
  3333.       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
  3334.       if (load_deplibs (*phandle, deplibs) == 0)
  3335.     {
  3336.       newhandle = *phandle;
  3337.       /* find_module may replace newhandle */
  3338.       if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
  3339.         {
  3340.           unload_deplibs (*phandle);
  3341.           ++errors;
  3342.         }
  3343.     }
  3344.       else
  3345.     {
  3346.       ++errors;
  3347.     }
  3348.  
  3349.       free_vars (dlname, old_name, libdir, deplibs);
  3350.       if (errors)
  3351.     {
  3352.       LT_DLFREE (*phandle);
  3353.       goto cleanup;
  3354.     }
  3355.  
  3356.       if (*phandle != newhandle)
  3357.     {
  3358.       unload_deplibs (*phandle);
  3359.     }
  3360.     }
  3361.   else
  3362.     {
  3363.       /* not a libtool module */
  3364.       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
  3365.       if (*phandle == 0)
  3366.     {
  3367.       ++errors;
  3368.       goto cleanup;
  3369.     }
  3370.  
  3371.       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
  3372.       newhandle = *phandle;
  3373.  
  3374.       /* If the module has no directory name component, try to find it
  3375.      first in user_search_path and then other prescribed paths.
  3376.      Otherwise (or in any case if the module was not yet found) try
  3377.      opening just the module name as passed.  */
  3378.       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
  3379.            && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
  3380.                     &newhandle)
  3381. #ifdef LTDL_SHLIBPATH_VAR
  3382.            && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
  3383.                     &newhandle)
  3384. #endif
  3385. #ifdef LTDL_SYSSEARCHPATH
  3386.            && !find_handle (sys_search_path, base_name, &newhandle)
  3387. #endif
  3388.            )))
  3389.     {
  3390.           if (tryall_dlopen (&newhandle, filename) != 0)
  3391.             {
  3392.               newhandle = NULL;
  3393.             }
  3394.     }
  3395.  
  3396.       if (!newhandle)
  3397.     {
  3398.       LT_DLFREE (*phandle);
  3399.       ++errors;
  3400.       goto cleanup;
  3401.     }
  3402.     }
  3403.  
  3404.  register_handle:
  3405.   LT_DLMEM_REASSIGN (*phandle, newhandle);
  3406.  
  3407.   if ((*phandle)->info.ref_count == 0)
  3408.     {
  3409.       (*phandle)->info.ref_count    = 1;
  3410.       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
  3411.  
  3412.       LT_DLMUTEX_LOCK ();
  3413.       (*phandle)->next        = handles;
  3414.       handles            = *phandle;
  3415.       LT_DLMUTEX_UNLOCK ();
  3416.     }
  3417.  
  3418.   LT_DLMUTEX_SETERROR (saved_error);
  3419.  
  3420.  cleanup:
  3421.   LT_DLFREE (dir);
  3422.   LT_DLFREE (name);
  3423.   LT_DLFREE (canonical);
  3424.  
  3425.   return errors;
  3426. }
  3427.  
  3428. lt_dlhandle
  3429. lt_dlopen (filename)
  3430.      const char *filename;
  3431. {
  3432.   lt_dlhandle handle = 0;
  3433.  
  3434.   /* Just incase we missed a code path in try_dlopen() that reports
  3435.      an error, but forgets to reset handle... */
  3436.   if (try_dlopen (&handle, filename) != 0)
  3437.     return 0;
  3438.  
  3439.   return handle;
  3440. }
  3441.  
  3442. /* If the last error messge store was `FILE_NOT_FOUND', then return
  3443.    non-zero.  */
  3444. static int
  3445. file_not_found ()
  3446. {
  3447.   const char *error = 0;
  3448.  
  3449.   LT_DLMUTEX_GETERROR (error);
  3450.   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
  3451.     return 1;
  3452.  
  3453.   return 0;
  3454. }
  3455.  
  3456. /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
  3457.    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
  3458.    and if a file is still not found try again with SHLIB_EXT appended
  3459.    instead.  */
  3460. lt_dlhandle
  3461. lt_dlopenext (filename)
  3462.      const char *filename;
  3463. {
  3464.   lt_dlhandle    handle        = 0;
  3465.   char *    tmp        = 0;
  3466.   char *    ext        = 0;
  3467.   size_t    len;
  3468.   int        errors        = 0;
  3469.  
  3470.   if (!filename)
  3471.     {
  3472.       return lt_dlopen (filename);
  3473.     }
  3474.  
  3475.   assert (filename);
  3476.  
  3477.   len = LT_STRLEN (filename);
  3478.   ext = strrchr (filename, '.');
  3479.  
  3480.   /* If FILENAME already bears a suitable extension, there is no need
  3481.      to try appending additional extensions.  */
  3482.   if (ext && ((strcmp (ext, archive_ext) == 0)
  3483. #ifdef LTDL_SHLIB_EXT
  3484.           || (strcmp (ext, shlib_ext) == 0)
  3485. #endif
  3486.       ))
  3487.     {
  3488.       return lt_dlopen (filename);
  3489.     }
  3490.  
  3491.   /* First try appending ARCHIVE_EXT.  */
  3492.   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
  3493.   if (!tmp)
  3494.     return 0;
  3495.  
  3496.   strcpy (tmp, filename);
  3497.   strcat (tmp, archive_ext);
  3498.   errors = try_dlopen (&handle, tmp);
  3499.  
  3500.   /* If we found FILENAME, stop searching -- whether we were able to
  3501.      load the file as a module or not.  If the file exists but loading
  3502.      failed, it is better to return an error message here than to
  3503.      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
  3504.      in the module search path.  */
  3505.   if (handle || ((errors > 0) && !file_not_found ()))
  3506.     {
  3507.       LT_DLFREE (tmp);
  3508.       return handle;
  3509.     }
  3510.  
  3511. #ifdef LTDL_SHLIB_EXT
  3512.   /* Try appending SHLIB_EXT.   */
  3513.   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
  3514.     {
  3515.       LT_DLFREE (tmp);
  3516.       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
  3517.       if (!tmp)
  3518.     return 0;
  3519.  
  3520.       strcpy (tmp, filename);
  3521.     }
  3522.   else
  3523.     {
  3524.       tmp[len] = LT_EOS_CHAR;
  3525.     }
  3526.  
  3527.   strcat(tmp, shlib_ext);
  3528.   errors = try_dlopen (&handle, tmp);
  3529.  
  3530.   /* As before, if the file was found but loading failed, return now
  3531.      with the current error message.  */
  3532.   if (handle || ((errors > 0) && !file_not_found ()))
  3533.     {
  3534.       LT_DLFREE (tmp);
  3535.       return handle;
  3536.     }
  3537. #endif
  3538.  
  3539.   /* Still here?  Then we really did fail to locate any of the file
  3540.      names we tried.  */
  3541.   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  3542.   LT_DLFREE (tmp);
  3543.   return 0;
  3544. }
  3545.  
  3546.  
  3547. static int
  3548. lt_argz_insert (pargz, pargz_len, before, entry)
  3549.      char **pargz;
  3550.      size_t *pargz_len;
  3551.      char *before;
  3552.      const char *entry;
  3553. {
  3554.   error_t error;
  3555.  
  3556.   /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
  3557.      pargz_len, NULL, entry) failed with EINVAL.  */
  3558.   if (before)
  3559.     error = argz_insert (pargz, pargz_len, before, entry);
  3560.   else
  3561.     error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
  3562.  
  3563.   if (error)
  3564.     {
  3565.       switch (error)
  3566.     {
  3567.     case ENOMEM:
  3568.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  3569.       break;
  3570.     default:
  3571.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
  3572.       break;
  3573.     }
  3574.       return 1;
  3575.     }
  3576.  
  3577.   return 0;
  3578. }
  3579.  
  3580. static int
  3581. lt_argz_insertinorder (pargz, pargz_len, entry)
  3582.      char **pargz;
  3583.      size_t *pargz_len;
  3584.      const char *entry;
  3585. {
  3586.   char *before = 0;
  3587.  
  3588.   assert (pargz);
  3589.   assert (pargz_len);
  3590.   assert (entry && *entry);
  3591.  
  3592.   if (*pargz)
  3593.     while ((before = argz_next (*pargz, *pargz_len, before)))
  3594.       {
  3595.     int cmp = strcmp (entry, before);
  3596.  
  3597.     if (cmp < 0)  break;
  3598.     if (cmp == 0) return 0;    /* No duplicates! */
  3599.       }
  3600.  
  3601.   return lt_argz_insert (pargz, pargz_len, before, entry);
  3602. }
  3603.  
  3604. static int
  3605. lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
  3606.      char **pargz;
  3607.      size_t *pargz_len;
  3608.      const char *dirnam;
  3609.      struct dirent *dp;
  3610. {
  3611.   char   *buf        = 0;
  3612.   size_t buf_len    = 0;
  3613.   char   *end        = 0;
  3614.   size_t end_offset = 0;
  3615.   size_t dir_len    = 0;
  3616.   int    errors        = 0;
  3617.  
  3618.   assert (pargz);
  3619.   assert (pargz_len);
  3620.   assert (dp);
  3621.  
  3622.   dir_len = LT_STRLEN (dirnam);
  3623.   end     = dp->d_name + LT_D_NAMLEN(dp);
  3624.  
  3625.   /* Ignore version numbers.  */
  3626.   {
  3627.     char *p;
  3628.     for (p = end; p -1 > dp->d_name; --p)
  3629.       if (strchr (".0123456789", p[-1]) == 0)
  3630.     break;
  3631.  
  3632.     if (*p == '.')
  3633.       end = p;
  3634.   }
  3635.  
  3636.   /* Ignore filename extension.  */
  3637.   {
  3638.     char *p;
  3639.     for (p = end -1; p > dp->d_name; --p)
  3640.       if (*p == '.')
  3641.     {
  3642.       end = p;
  3643.       break;
  3644.     }
  3645.   }
  3646.  
  3647.   /* Prepend the directory name.  */
  3648.   end_offset    = end - dp->d_name;
  3649.   buf_len    = dir_len + 1+ end_offset;
  3650.   buf        = LT_EMALLOC (char, 1+ buf_len);
  3651.   if (!buf)
  3652.     return ++errors;
  3653.  
  3654.   assert (buf);
  3655.  
  3656.   strcpy  (buf, dirnam);
  3657.   strcat  (buf, "/");
  3658.   strncat (buf, dp->d_name, end_offset);
  3659.   buf[buf_len] = LT_EOS_CHAR;
  3660.  
  3661.   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
  3662.   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
  3663.     ++errors;
  3664.  
  3665.   LT_DLFREE (buf);
  3666.  
  3667.   return errors;
  3668. }
  3669.  
  3670. static int
  3671. list_files_by_dir (dirnam, pargz, pargz_len)
  3672.      const char *dirnam;
  3673.      char **pargz;
  3674.      size_t *pargz_len;
  3675. {
  3676.   DIR    *dirp      = 0;
  3677.   int    errors      = 0;
  3678.  
  3679.   assert (dirnam && *dirnam);
  3680.   assert (pargz);
  3681.   assert (pargz_len);
  3682.   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
  3683.  
  3684.   dirp = opendir (dirnam);
  3685.   if (dirp)
  3686.     {
  3687.       struct dirent *dp    = 0;
  3688.  
  3689.       while ((dp = readdir (dirp)))
  3690.     if (dp->d_name[0] != '.')
  3691.       if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
  3692.         {
  3693.           ++errors;
  3694.           break;
  3695.         }
  3696.  
  3697.       closedir (dirp);
  3698.     }
  3699.   else
  3700.     ++errors;
  3701.  
  3702.   return errors;
  3703. }
  3704.  
  3705.  
  3706. /* If there are any files in DIRNAME, call the function passed in
  3707.    DATA1 (with the name of each file and DATA2 as arguments).  */
  3708. static int
  3709. foreachfile_callback (dirname, data1, data2)
  3710.      char *dirname;
  3711.      lt_ptr data1;
  3712.      lt_ptr data2;
  3713. {
  3714.   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
  3715.     = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
  3716.  
  3717.   int      is_done  = 0;
  3718.   char   *argz     = 0;
  3719.   size_t  argz_len = 0;
  3720.  
  3721.   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
  3722.     goto cleanup;
  3723.   if (!argz)
  3724.     goto cleanup;
  3725.  
  3726.   {
  3727.     char *filename = 0;
  3728.     while ((filename = argz_next (argz, argz_len, filename)))
  3729.       if ((is_done = (*func) (filename, data2)))
  3730.     break;
  3731.   }
  3732.  
  3733.  cleanup:
  3734.   LT_DLFREE (argz);
  3735.  
  3736.   return is_done;
  3737. }
  3738.  
  3739.  
  3740. /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
  3741.    with DATA.  The filenames passed to FUNC would be suitable for
  3742.    passing to lt_dlopenext.  The extensions are stripped so that
  3743.    individual modules do not generate several entries (e.g. libfoo.la,
  3744.    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
  3745.    then the same directories that lt_dlopen would search are examined.  */
  3746. int
  3747. lt_dlforeachfile (search_path, func, data)
  3748.      const char *search_path;
  3749.      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
  3750.      lt_ptr data;
  3751. {
  3752.   int is_done = 0;
  3753.  
  3754.   if (search_path)
  3755.     {
  3756.       /* If a specific path was passed, search only the directories
  3757.      listed in it.  */
  3758.       is_done = foreach_dirinpath (search_path, 0,
  3759.                    foreachfile_callback, func, data);
  3760.     }
  3761.   else
  3762.     {
  3763.       /* Otherwise search the default paths.  */
  3764.       is_done = foreach_dirinpath (user_search_path, 0,
  3765.                    foreachfile_callback, func, data);
  3766.       if (!is_done)
  3767.     {
  3768.       is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
  3769.                        foreachfile_callback, func, data);
  3770.     }
  3771.  
  3772. #ifdef LTDL_SHLIBPATH_VAR
  3773.       if (!is_done)
  3774.     {
  3775.       is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
  3776.                        foreachfile_callback, func, data);
  3777.     }
  3778. #endif
  3779. #ifdef LTDL_SYSSEARCHPATH
  3780.       if (!is_done)
  3781.     {
  3782.       is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
  3783.                        foreachfile_callback, func, data);
  3784.     }
  3785. #endif
  3786.     }
  3787.  
  3788.   return is_done;
  3789. }
  3790.  
  3791. int
  3792. lt_dlclose (handle)
  3793.      lt_dlhandle handle;
  3794. {
  3795.   lt_dlhandle cur, last;
  3796.   int errors = 0;
  3797.  
  3798.   LT_DLMUTEX_LOCK ();
  3799.  
  3800.   /* check whether the handle is valid */
  3801.   last = cur = handles;
  3802.   while (cur && handle != cur)
  3803.     {
  3804.       last = cur;
  3805.       cur = cur->next;
  3806.     }
  3807.  
  3808.   if (!cur)
  3809.     {
  3810.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  3811.       ++errors;
  3812.       goto done;
  3813.     }
  3814.  
  3815.   handle->info.ref_count--;
  3816.  
  3817.   /* Note that even with resident modules, we must track the ref_count
  3818.      correctly incase the user decides to reset the residency flag
  3819.      later (even though the API makes no provision for that at the
  3820.      moment).  */
  3821.   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
  3822.     {
  3823.       lt_user_data data = handle->loader->dlloader_data;
  3824.  
  3825.       if (handle != handles)
  3826.     {
  3827.       last->next = handle->next;
  3828.     }
  3829.       else
  3830.     {
  3831.       handles = handle->next;
  3832.     }
  3833.  
  3834.       errors += handle->loader->module_close (data, handle->module);
  3835.       errors += unload_deplibs(handle);
  3836.  
  3837.       /* It is up to the callers to free the data itself.  */
  3838.       LT_DLFREE (handle->caller_data);
  3839.  
  3840.       LT_DLFREE (handle->info.filename);
  3841.       LT_DLFREE (handle->info.name);
  3842.       LT_DLFREE (handle);
  3843.  
  3844.       goto done;
  3845.     }
  3846.  
  3847.   if (LT_DLIS_RESIDENT (handle))
  3848.     {
  3849.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
  3850.       ++errors;
  3851.     }
  3852.  
  3853.  done:
  3854.   LT_DLMUTEX_UNLOCK ();
  3855.  
  3856.   return errors;
  3857. }
  3858.  
  3859. lt_ptr
  3860. lt_dlsym (handle, symbol)
  3861.      lt_dlhandle handle;
  3862.      const char *symbol;
  3863. {
  3864.   size_t lensym;
  3865.   char    lsym[LT_SYMBOL_LENGTH];
  3866.   char    *sym;
  3867.   lt_ptr address;
  3868.   lt_user_data data;
  3869.  
  3870.   if (!handle)
  3871.     {
  3872.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  3873.       return 0;
  3874.     }
  3875.  
  3876.   if (!symbol)
  3877.     {
  3878.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  3879.       return 0;
  3880.     }
  3881.  
  3882.   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
  3883.                     + LT_STRLEN (handle->info.name);
  3884.  
  3885.   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
  3886.     {
  3887.       sym = lsym;
  3888.     }
  3889.   else
  3890.     {
  3891.       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
  3892.       if (!sym)
  3893.     {
  3894.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
  3895.       return 0;
  3896.     }
  3897.     }
  3898.  
  3899.   data = handle->loader->dlloader_data;
  3900.   if (handle->info.name)
  3901.     {
  3902.       const char *saved_error;
  3903.  
  3904.       LT_DLMUTEX_GETERROR (saved_error);
  3905.  
  3906.       /* this is a libtool module */
  3907.       if (handle->loader->sym_prefix)
  3908.     {
  3909.       strcpy(sym, handle->loader->sym_prefix);
  3910.       strcat(sym, handle->info.name);
  3911.     }
  3912.       else
  3913.     {
  3914.       strcpy(sym, handle->info.name);
  3915.     }
  3916.  
  3917.       strcat(sym, "_LTX_");
  3918.       strcat(sym, symbol);
  3919.  
  3920.       /* try "modulename_LTX_symbol" */
  3921.       address = handle->loader->find_sym (data, handle->module, sym);
  3922.       if (address)
  3923.     {
  3924.       if (sym != lsym)
  3925.         {
  3926.           LT_DLFREE (sym);
  3927.         }
  3928.       return address;
  3929.     }
  3930.       LT_DLMUTEX_SETERROR (saved_error);
  3931.     }
  3932.  
  3933.   /* otherwise try "symbol" */
  3934.   if (handle->loader->sym_prefix)
  3935.     {
  3936.       strcpy(sym, handle->loader->sym_prefix);
  3937.       strcat(sym, symbol);
  3938.     }
  3939.   else
  3940.     {
  3941.       strcpy(sym, symbol);
  3942.     }
  3943.  
  3944.   address = handle->loader->find_sym (data, handle->module, sym);
  3945.   if (sym != lsym)
  3946.     {
  3947.       LT_DLFREE (sym);
  3948.     }
  3949.  
  3950.   return address;
  3951. }
  3952.  
  3953. const char *
  3954. lt_dlerror ()
  3955. {
  3956.   const char *error;
  3957.  
  3958.   LT_DLMUTEX_GETERROR (error);
  3959.   LT_DLMUTEX_SETERROR (0);
  3960.  
  3961.   return error ? error : NULL;
  3962. }
  3963.  
  3964. static int
  3965. lt_dlpath_insertdir (ppath, before, dir)
  3966.      char **ppath;
  3967.      char *before;
  3968.      const char *dir;
  3969. {
  3970.   int    errors        = 0;
  3971.   char  *canonical    = 0;
  3972.   char  *argz        = 0;
  3973.   size_t argz_len    = 0;
  3974.  
  3975.   assert (ppath);
  3976.   assert (dir && *dir);
  3977.  
  3978.   if (canonicalize_path (dir, &canonical) != 0)
  3979.     {
  3980.       ++errors;
  3981.       goto cleanup;
  3982.     }
  3983.  
  3984.   assert (canonical && *canonical);
  3985.  
  3986.   /* If *PPATH is empty, set it to DIR.  */
  3987.   if (*ppath == 0)
  3988.     {
  3989.       assert (!before);        /* BEFORE cannot be set without PPATH.  */
  3990.       assert (dir);        /* Without DIR, don't call this function!  */
  3991.  
  3992.       *ppath = lt_estrdup (dir);
  3993.       if (*ppath == 0)
  3994.     ++errors;
  3995.  
  3996.       return errors;
  3997.     }
  3998.  
  3999.   assert (ppath && *ppath);
  4000.  
  4001.   if (argzize_path (*ppath, &argz, &argz_len) != 0)
  4002.     {
  4003.       ++errors;
  4004.       goto cleanup;
  4005.     }
  4006.  
  4007.   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
  4008.      if *PPATH is already canonicalized, and hence does not change length
  4009.      with respect to ARGZ.  We canonicalize each entry as it is added to
  4010.      the search path, and don't call this function with (uncanonicalized)
  4011.      user paths, so this is a fair assumption.  */
  4012.   if (before)
  4013.     {
  4014.       assert (*ppath <= before);
  4015.       assert (before - *ppath <= strlen (*ppath));
  4016.  
  4017.       before = before - *ppath + argz;
  4018.     }
  4019.  
  4020.   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
  4021.     {
  4022.       ++errors;
  4023.       goto cleanup;
  4024.     }
  4025.  
  4026.   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
  4027.   LT_DLMEM_REASSIGN (*ppath,  argz);
  4028.  
  4029.  cleanup:
  4030.   LT_DLFREE (canonical);
  4031.   LT_DLFREE (argz);
  4032.  
  4033.   return errors;
  4034. }
  4035.  
  4036. int
  4037. lt_dladdsearchdir (search_dir)
  4038.      const char *search_dir;
  4039. {
  4040.   int errors = 0;
  4041.  
  4042.   if (search_dir && *search_dir)
  4043.     {
  4044.       LT_DLMUTEX_LOCK ();
  4045.       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
  4046.     ++errors;
  4047.       LT_DLMUTEX_UNLOCK ();
  4048.     }
  4049.  
  4050.   return errors;
  4051. }
  4052.  
  4053. int
  4054. lt_dlinsertsearchdir (before, search_dir)
  4055.      const char *before;
  4056.      const char *search_dir;
  4057. {
  4058.   int errors = 0;
  4059.  
  4060.   if (before)
  4061.     {
  4062.       LT_DLMUTEX_LOCK ();
  4063.       if ((before < user_search_path)
  4064.       || (before >= user_search_path + LT_STRLEN (user_search_path)))
  4065.     {
  4066.       LT_DLMUTEX_UNLOCK ();
  4067.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
  4068.       return 1;
  4069.     }
  4070.       LT_DLMUTEX_UNLOCK ();
  4071.     }
  4072.  
  4073.   if (search_dir && *search_dir)
  4074.     {
  4075.       LT_DLMUTEX_LOCK ();
  4076.       if (lt_dlpath_insertdir (&user_search_path,
  4077.                    (char *) before, search_dir) != 0)
  4078.     {
  4079.       ++errors;
  4080.     }
  4081.       LT_DLMUTEX_UNLOCK ();
  4082.     }
  4083.  
  4084.   return errors;
  4085. }
  4086.  
  4087. int
  4088. lt_dlsetsearchpath (search_path)
  4089.      const char *search_path;
  4090. {
  4091.   int   errors        = 0;
  4092.  
  4093.   LT_DLMUTEX_LOCK ();
  4094.   LT_DLFREE (user_search_path);
  4095.   LT_DLMUTEX_UNLOCK ();
  4096.  
  4097.   if (!search_path || !LT_STRLEN (search_path))
  4098.     {
  4099.       return errors;
  4100.     }
  4101.  
  4102.   LT_DLMUTEX_LOCK ();
  4103.   if (canonicalize_path (search_path, &user_search_path) != 0)
  4104.     ++errors;
  4105.   LT_DLMUTEX_UNLOCK ();
  4106.  
  4107.   return errors;
  4108. }
  4109.  
  4110. const char *
  4111. lt_dlgetsearchpath ()
  4112. {
  4113.   const char *saved_path;
  4114.  
  4115.   LT_DLMUTEX_LOCK ();
  4116.   saved_path = user_search_path;
  4117.   LT_DLMUTEX_UNLOCK ();
  4118.  
  4119.   return saved_path;
  4120. }
  4121.  
  4122. int
  4123. lt_dlmakeresident (handle)
  4124.      lt_dlhandle handle;
  4125. {
  4126.   int errors = 0;
  4127.  
  4128.   if (!handle)
  4129.     {
  4130.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  4131.       ++errors;
  4132.     }
  4133.   else
  4134.     {
  4135.       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
  4136.     }
  4137.  
  4138.   return errors;
  4139. }
  4140.  
  4141. int
  4142. lt_dlisresident    (handle)
  4143.      lt_dlhandle handle;
  4144. {
  4145.   if (!handle)
  4146.     {
  4147.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  4148.       return -1;
  4149.     }
  4150.  
  4151.   return LT_DLIS_RESIDENT (handle);
  4152. }
  4153.  
  4154.  
  4155.  
  4156.  
  4157. /* --- MODULE INFORMATION --- */
  4158.  
  4159. const lt_dlinfo *
  4160. lt_dlgetinfo (handle)
  4161.      lt_dlhandle handle;
  4162. {
  4163.   if (!handle)
  4164.     {
  4165.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  4166.       return 0;
  4167.     }
  4168.  
  4169.   return &(handle->info);
  4170. }
  4171.  
  4172. lt_dlhandle
  4173. lt_dlhandle_next (place)
  4174.      lt_dlhandle place;
  4175. {
  4176.   return place ? place->next : handles;
  4177. }
  4178.  
  4179. int
  4180. lt_dlforeach (func, data)
  4181.      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
  4182.      lt_ptr data;
  4183. {
  4184.   int errors = 0;
  4185.   lt_dlhandle cur;
  4186.  
  4187.   LT_DLMUTEX_LOCK ();
  4188.  
  4189.   cur = handles;
  4190.   while (cur)
  4191.     {
  4192.       lt_dlhandle tmp = cur;
  4193.  
  4194.       cur = cur->next;
  4195.       if ((*func) (tmp, data))
  4196.     {
  4197.       ++errors;
  4198.       break;
  4199.     }
  4200.     }
  4201.  
  4202.   LT_DLMUTEX_UNLOCK ();
  4203.  
  4204.   return errors;
  4205. }
  4206.  
  4207. lt_dlcaller_id
  4208. lt_dlcaller_register ()
  4209. {
  4210.   static lt_dlcaller_id last_caller_id = 0;
  4211.   int result;
  4212.  
  4213.   LT_DLMUTEX_LOCK ();
  4214.   result = ++last_caller_id;
  4215.   LT_DLMUTEX_UNLOCK ();
  4216.  
  4217.   return result;
  4218. }
  4219.  
  4220. lt_ptr
  4221. lt_dlcaller_set_data (key, handle, data)
  4222.      lt_dlcaller_id key;
  4223.      lt_dlhandle handle;
  4224.      lt_ptr data;
  4225. {
  4226.   int n_elements = 0;
  4227.   lt_ptr stale = (lt_ptr) 0;
  4228.   int i;
  4229.  
  4230.   /* This needs to be locked so that the caller data can be updated
  4231.      simultaneously by different threads.  */
  4232.   LT_DLMUTEX_LOCK ();
  4233.  
  4234.   if (handle->caller_data)
  4235.     while (handle->caller_data[n_elements].key)
  4236.       ++n_elements;
  4237.  
  4238.   for (i = 0; i < n_elements; ++i)
  4239.     {
  4240.       if (handle->caller_data[i].key == key)
  4241.     {
  4242.       stale = handle->caller_data[i].data;
  4243.       break;
  4244.     }
  4245.     }
  4246.  
  4247.   /* Ensure that there is enough room in this handle's caller_data
  4248.      array to accept a new element (and an empty end marker).  */
  4249.   if (i == n_elements)
  4250.     {
  4251.       lt_caller_data *temp
  4252.     = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
  4253.  
  4254.       if (!temp)
  4255.     {
  4256.       stale = 0;
  4257.       goto done;
  4258.     }
  4259.  
  4260.       handle->caller_data = temp;
  4261.  
  4262.       /* We only need this if we needed to allocate a new caller_data.  */
  4263.       handle->caller_data[i].key  = key;
  4264.       handle->caller_data[1+ i].key = 0;
  4265.     }
  4266.  
  4267.   handle->caller_data[i].data = data;
  4268.  
  4269.  done:
  4270.   LT_DLMUTEX_UNLOCK ();
  4271.  
  4272.   return stale;
  4273. }
  4274.  
  4275. lt_ptr
  4276. lt_dlcaller_get_data  (key, handle)
  4277.      lt_dlcaller_id key;
  4278.      lt_dlhandle handle;
  4279. {
  4280.   lt_ptr result = (lt_ptr) 0;
  4281.  
  4282.   /* This needs to be locked so that the caller data isn't updated by
  4283.      another thread part way through this function.  */
  4284.   LT_DLMUTEX_LOCK ();
  4285.  
  4286.   /* Locate the index of the element with a matching KEY.  */
  4287.   {
  4288.     int i;
  4289.     for (i = 0; handle->caller_data[i].key; ++i)
  4290.       {
  4291.     if (handle->caller_data[i].key == key)
  4292.       {
  4293.         result = handle->caller_data[i].data;
  4294.         break;
  4295.       }
  4296.       }
  4297.   }
  4298.  
  4299.   LT_DLMUTEX_UNLOCK ();
  4300.  
  4301.   return result;
  4302. }
  4303.  
  4304.  
  4305.  
  4306. /* --- USER MODULE LOADER API --- */
  4307.  
  4308.  
  4309. int
  4310. lt_dlloader_add (place, dlloader, loader_name)
  4311.      lt_dlloader *place;
  4312.      const struct lt_user_dlloader *dlloader;
  4313.      const char *loader_name;
  4314. {
  4315.   int errors = 0;
  4316.   lt_dlloader *node = 0, *ptr = 0;
  4317.  
  4318.   if ((dlloader == 0)    /* diagnose null parameters */
  4319.       || (dlloader->module_open == 0)
  4320.       || (dlloader->module_close == 0)
  4321.       || (dlloader->find_sym == 0))
  4322.     {
  4323.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
  4324.       return 1;
  4325.     }
  4326.  
  4327.   /* Create a new dlloader node with copies of the user callbacks.  */
  4328.   node = LT_EMALLOC (lt_dlloader, 1);
  4329.   if (!node)
  4330.     return 1;
  4331.  
  4332.   node->next        = 0;
  4333.   node->loader_name    = loader_name;
  4334.   node->sym_prefix    = dlloader->sym_prefix;
  4335.   node->dlloader_exit    = dlloader->dlloader_exit;
  4336.   node->module_open    = dlloader->module_open;
  4337.   node->module_close    = dlloader->module_close;
  4338.   node->find_sym    = dlloader->find_sym;
  4339.   node->dlloader_data    = dlloader->dlloader_data;
  4340.  
  4341.   LT_DLMUTEX_LOCK ();
  4342.   if (!loaders)
  4343.     {
  4344.       /* If there are no loaders, NODE becomes the list! */
  4345.       loaders = node;
  4346.     }
  4347.   else if (!place)
  4348.     {
  4349.       /* If PLACE is not set, add NODE to the end of the
  4350.      LOADERS list. */
  4351.       for (ptr = loaders; ptr->next; ptr = ptr->next)
  4352.     {
  4353.       /*NOWORK*/;
  4354.     }
  4355.  
  4356.       ptr->next = node;
  4357.     }
  4358.   else if (loaders == place)
  4359.     {
  4360.       /* If PLACE is the first loader, NODE goes first. */
  4361.       node->next = place;
  4362.       loaders = node;
  4363.     }
  4364.   else
  4365.     {
  4366.       /* Find the node immediately preceding PLACE. */
  4367.       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
  4368.     {
  4369.       /*NOWORK*/;
  4370.     }
  4371.  
  4372.       if (ptr->next != place)
  4373.     {
  4374.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
  4375.       ++errors;
  4376.     }
  4377.       else
  4378.     {
  4379.       /* Insert NODE between PTR and PLACE. */
  4380.       node->next = place;
  4381.       ptr->next  = node;
  4382.     }
  4383.     }
  4384.  
  4385.   LT_DLMUTEX_UNLOCK ();
  4386.  
  4387.   return errors;
  4388. }
  4389.  
  4390. int
  4391. lt_dlloader_remove (loader_name)
  4392.      const char *loader_name;
  4393. {
  4394.   lt_dlloader *place = lt_dlloader_find (loader_name);
  4395.   lt_dlhandle handle;
  4396.   int errors = 0;
  4397.  
  4398.   if (!place)
  4399.     {
  4400.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
  4401.       return 1;
  4402.     }
  4403.  
  4404.   LT_DLMUTEX_LOCK ();
  4405.  
  4406.   /* Fail if there are any open modules which use this loader. */
  4407.   for  (handle = handles; handle; handle = handle->next)
  4408.     {
  4409.       if (handle->loader == place)
  4410.     {
  4411.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
  4412.       ++errors;
  4413.       goto done;
  4414.     }
  4415.     }
  4416.  
  4417.   if (place == loaders)
  4418.     {
  4419.       /* PLACE is the first loader in the list. */
  4420.       loaders = loaders->next;
  4421.     }
  4422.   else
  4423.     {
  4424.       /* Find the loader before the one being removed. */
  4425.       lt_dlloader *prev;
  4426.       for (prev = loaders; prev->next; prev = prev->next)
  4427.     {
  4428.       if (!strcmp (prev->next->loader_name, loader_name))
  4429.         {
  4430.           break;
  4431.         }
  4432.     }
  4433.  
  4434.       place = prev->next;
  4435.       prev->next = prev->next->next;
  4436.     }
  4437.  
  4438.   if (place->dlloader_exit)
  4439.     {
  4440.       errors = place->dlloader_exit (place->dlloader_data);
  4441.     }
  4442.  
  4443.   LT_DLFREE (place);
  4444.  
  4445.  done:
  4446.   LT_DLMUTEX_UNLOCK ();
  4447.  
  4448.   return errors;
  4449. }
  4450.  
  4451. lt_dlloader *
  4452. lt_dlloader_next (place)
  4453.      lt_dlloader *place;
  4454. {
  4455.   lt_dlloader *next;
  4456.  
  4457.   LT_DLMUTEX_LOCK ();
  4458.   next = place ? place->next : loaders;
  4459.   LT_DLMUTEX_UNLOCK ();
  4460.  
  4461.   return next;
  4462. }
  4463.  
  4464. const char *
  4465. lt_dlloader_name (place)
  4466.      lt_dlloader *place;
  4467. {
  4468.   const char *name = 0;
  4469.  
  4470.   if (place)
  4471.     {
  4472.       LT_DLMUTEX_LOCK ();
  4473.       name = place ? place->loader_name : 0;
  4474.       LT_DLMUTEX_UNLOCK ();
  4475.     }
  4476.   else
  4477.     {
  4478.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
  4479.     }
  4480.  
  4481.   return name;
  4482. }
  4483.  
  4484. lt_user_data *
  4485. lt_dlloader_data (place)
  4486.      lt_dlloader *place;
  4487. {
  4488.   lt_user_data *data = 0;
  4489.  
  4490.   if (place)
  4491.     {
  4492.       LT_DLMUTEX_LOCK ();
  4493.       data = place ? &(place->dlloader_data) : 0;
  4494.       LT_DLMUTEX_UNLOCK ();
  4495.     }
  4496.   else
  4497.     {
  4498.       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
  4499.     }
  4500.  
  4501.   return data;
  4502. }
  4503.  
  4504. lt_dlloader *
  4505. lt_dlloader_find (loader_name)
  4506.      const char *loader_name;
  4507. {
  4508.   lt_dlloader *place = 0;
  4509.  
  4510.   LT_DLMUTEX_LOCK ();
  4511.   for (place = loaders; place; place = place->next)
  4512.     {
  4513.       if (strcmp (place->loader_name, loader_name) == 0)
  4514.     {
  4515.       break;
  4516.     }
  4517.     }
  4518.   LT_DLMUTEX_UNLOCK ();
  4519.  
  4520.   return place;
  4521. }
  4522.